blob: 59d5b738ba8f4013b3ccc56e4fd42eff73ad351d [file] [log] [blame]
// Copyright 2016 PDFium Authors. All rights reserved.
// 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 <algorithm>
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/cfx_readonlymemorystream.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_extension.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/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cfxjse_value.h"
#include "fxjs/xfa/cjx_node.h"
#include "third_party/base/compiler_specific.h"
#include "third_party/base/logging.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/span.h"
#include "third_party/base/stl_util.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_ffwidget.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_deltas.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_parser.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 g_inv_base64[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 ? g_inv_base64[x] : 255;
}
std::vector<uint8_t> XFA_RemoveBase64Whitespace(
pdfium::span<const uint8_t> spStr) {
std::vector<uint8_t> result;
result.reserve(spStr.size());
for (uint8_t ch : spStr) {
if (GetInvBase64(ch) != 255 || ch == '=')
result.push_back(ch);
}
return result;
}
std::vector<uint8_t> XFA_Base64Decode(const ByteString& bsStr) {
std::vector<uint8_t> result;
if (bsStr.IsEmpty())
return result;
std::vector<uint8_t> 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)g_inv_base64[buffer[i]] << 6) |
((uint32_t)g_inv_base64[buffer[i + 1]]);
result.push_back((uint8_t)(dwLimb >> 4) & 0xFF);
} else {
dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 12) |
((uint32_t)g_inv_base64[buffer[i + 1]] << 6) |
((uint32_t)g_inv_base64[buffer[i + 2]]);
result.push_back((uint8_t)(dwLimb >> 10) & 0xFF);
result.push_back((uint8_t)(dwLimb >> 2) & 0xFF);
}
} else {
dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 18) |
((uint32_t)g_inv_base64[buffer[i + 1]] << 12) |
((uint32_t)g_inv_base64[buffer[i + 2]] << 6) |
((uint32_t)g_inv_base64[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<CFX_DIBitmap> 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());
ByteString bsData; // Must outlive |pImageFileRead|.
std::vector<uint8_t> buffer; // Must outlive |pImageFileRead|.
RetainPtr<IFX_SeekableReadStream> pImageFileRead;
if (wsImage.GetLength() > 0) {
XFA_AttributeValue iEncoding = pImage->GetTransferEncoding();
if (iEncoding == XFA_AttributeValue::Base64) {
bsData = wsImage.ToUTF8();
buffer = XFA_Base64Decode(bsData);
if (!buffer.empty())
pImageFileRead = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(buffer);
} else {
bsData = wsImage.ToDefANSI();
pImageFileRead =
pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(bsData.raw_span());
}
} else {
WideString wsURL = wsHref;
if (!(wsURL.Left(7).EqualsASCII("http://") ||
wsURL.Left(6).EqualsASCII("ftp://"))) {
RetainPtr<CFX_DIBitmap> pBitmap =
pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi);
if (pBitmap) {
bNameImage = true;
return pBitmap;
}
}
pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL);
}
if (!pImageFileRead)
return nullptr;
bNameImage = false;
RetainPtr<CFX_DIBitmap> pBitmap =
XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi);
return pBitmap;
}
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.Left(nSplitIndex.value());
if (!wsDate.IsEmpty()) {
if (!std::any_of(wsDate.begin(), wsDate.end(),
[](wchar_t c) { return FXSYS_IsDecimalDigit(c); })) {
return false;
}
}
wsTime = wsDateTime.Right(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;
}
std::vector<CXFA_Node*> NodesSortedByDocumentIdx(
const std::set<CXFA_Node*>& rgNodeSet) {
if (rgNodeSet.empty())
return std::vector<CXFA_Node*>();
std::vector<CXFA_Node*> rgNodeArray;
CXFA_Node* pCommonParent = (*rgNodeSet.begin())->GetParent();
for (CXFA_Node* pNode = pCommonParent->GetFirstChild(); pNode;
pNode = pNode->GetNextSibling()) {
if (pdfium::ContainsValue(rgNodeSet, pNode))
rgNodeArray.push_back(pNode);
}
return rgNodeArray;
}
using CXFA_NodeSetPair = std::pair<std::set<CXFA_Node*>, std::set<CXFA_Node*>>;
using CXFA_NodeSetPairMap =
std::map<uint32_t, std::unique_ptr<CXFA_NodeSetPair>>;
using CXFA_NodeSetPairMapMap =
std::map<CXFA_Node*, std::unique_ptr<CXFA_NodeSetPairMap>>;
CXFA_NodeSetPair* NodeSetPairForNode(CXFA_Node* pNode,
CXFA_NodeSetPairMapMap* pMap) {
CXFA_Node* pParentNode = pNode->GetParent();
uint32_t dwNameHash = pNode->GetNameHash();
if (!pParentNode || !dwNameHash)
return nullptr;
if (!(*pMap)[pParentNode])
(*pMap)[pParentNode] = pdfium::MakeUnique<CXFA_NodeSetPairMap>();
CXFA_NodeSetPairMap* pNodeSetPairMap = (*pMap)[pParentNode].get();
if (!(*pNodeSetPairMap)[dwNameHash])
(*pNodeSetPairMap)[dwNameHash] = pdfium::MakeUnique<CXFA_NodeSetPair>();
return (*pNodeSetPairMap)[dwNameHash].get();
}
void ReorderDataNodes(const std::set<CXFA_Node*>& sSet1,
const std::set<CXFA_Node*>& sSet2,
bool bInsertBefore) {
CXFA_NodeSetPairMapMap rgMap;
for (CXFA_Node* pNode : sSet1) {
CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap);
if (pNodeSetPair)
pNodeSetPair->first.insert(pNode);
}
for (CXFA_Node* pNode : sSet2) {
CXFA_NodeSetPair* pNodeSetPair = NodeSetPairForNode(pNode, &rgMap);
if (pNodeSetPair) {
if (pdfium::ContainsValue(pNodeSetPair->first, pNode))
pNodeSetPair->first.erase(pNode);
else
pNodeSetPair->second.insert(pNode);
}
}
for (const auto& iter1 : rgMap) {
CXFA_NodeSetPairMap* pNodeSetPairMap = iter1.second.get();
if (!pNodeSetPairMap)
continue;
for (const auto& iter2 : *pNodeSetPairMap) {
CXFA_NodeSetPair* pNodeSetPair = iter2.second.get();
if (!pNodeSetPair)
continue;
if (!pNodeSetPair->first.empty() && !pNodeSetPair->second.empty()) {
std::vector<CXFA_Node*> rgNodeArray1 =
NodesSortedByDocumentIdx(pNodeSetPair->first);
std::vector<CXFA_Node*> 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<CXFA_Stroke*>& 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);
}
auto dot_index = wsSrcNum.Find('.');
dot_index = !dot_index.has_value() ? wsSrcNum.GetLength() : dot_index;
if (dot_index.value() < 1)
return WideString();
size_t nPos = dot_index.value() % 3;
WideString wsOutput;
for (size_t i = 0; i < dot_index.value(); i++) {
if (i % 3 == nPos && i != 0)
wsOutput += wsGroupSymbol;
wsOutput += wsSrcNum[i];
}
if (dot_index.value() < wsSrcNum.GetLength()) {
wsOutput += pLocale->GetDecimalSymbol();
wsOutput += wsSrcNum.Right(wsSrcNum.GetLength() - dot_index.value() - 1);
}
if (bNeg)
return pLocale->GetMinusSymbol() + wsOutput;
return wsOutput;
}
CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent,
uint32_t dwNameHash,
uint32_t dwFilter);
CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent,
XFA_Element element,
uint32_t dwFilter);
CXFA_Node* FindFirstSiblingNamed(CXFA_Node* parent, uint32_t dwNameHash) {
CXFA_Node* result = FindFirstSiblingNamedInList(parent, dwNameHash,
XFA_NODEFILTER_Properties);
if (result)
return result;
return FindFirstSiblingNamedInList(parent, dwNameHash,
XFA_NODEFILTER_Children);
}
CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent,
uint32_t dwNameHash,
uint32_t 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_Properties);
if (result)
return result;
return FindFirstSiblingOfClassInList(parent, element,
XFA_NODEFILTER_Children);
}
CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent,
XFA_Element element,
uint32_t 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<CXFA_Node*>* pSiblings,
bool bIsClassName,
bool bIsFindProperty) {
ASSERT(parent);
ASSERT(pSiblings);
if (bIsFindProperty) {
for (CXFA_Node* child :
parent->GetNodeListWithFilter(XFA_NODEFILTER_Properties)) {
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, false);
}
}
if (!pSiblings->empty())
return;
}
for (CXFA_Node* child :
parent->GetNodeListWithFilter(XFA_NODEFILTER_Children)) {
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, false);
}
}
}
} // namespace
class CXFA_WidgetLayoutData {
public:
CXFA_WidgetLayoutData() = default;
virtual ~CXFA_WidgetLayoutData() = default;
virtual CXFA_FieldLayoutData* AsFieldLayoutData() { return nullptr; }
virtual CXFA_ImageLayoutData* AsImageLayoutData() { return nullptr; }
virtual CXFA_TextLayoutData* AsTextLayoutData() { return nullptr; }
float m_fWidgetHeight = -1.0f;
};
class CXFA_TextLayoutData final : public CXFA_WidgetLayoutData {
public:
CXFA_TextLayoutData() = default;
~CXFA_TextLayoutData() override = default;
CXFA_TextLayoutData* AsTextLayoutData() override { return this; }
CXFA_TextLayout* GetTextLayout() const { return m_pTextLayout.get(); }
CXFA_TextProvider* GetTextProvider() const { return m_pTextProvider.get(); }
void LoadText(CXFA_FFDoc* doc, CXFA_Node* pNode) {
if (m_pTextLayout)
return;
m_pTextProvider =
pdfium::MakeUnique<CXFA_TextProvider>(pNode, XFA_TEXTPROVIDERTYPE_Text);
m_pTextLayout =
pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pTextProvider.get());
}
private:
std::unique_ptr<CXFA_TextLayout> m_pTextLayout;
std::unique_ptr<CXFA_TextProvider> m_pTextProvider;
};
class CXFA_ImageLayoutData final : public CXFA_WidgetLayoutData {
public:
CXFA_ImageLayoutData() = default;
~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->SetImageImage(XFA_LoadImageData(doc, image, m_bNamedImage,
m_iImageXDpi, m_iImageYDpi));
return !!m_pDIBitmap;
}
bool m_bNamedImage = false;
int32_t m_iImageXDpi = 0;
int32_t m_iImageYDpi = 0;
RetainPtr<CFX_DIBitmap> m_pDIBitmap;
};
class CXFA_FieldLayoutData : public CXFA_WidgetLayoutData {
public:
CXFA_FieldLayoutData() = default;
~CXFA_FieldLayoutData() override = default;
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 = pdfium::MakeUnique<CXFA_TextProvider>(
pNode, XFA_TEXTPROVIDERTYPE_Caption);
m_pCapTextLayout =
pdfium::MakeUnique<CXFA_TextLayout>(doc, m_pCapTextProvider.get());
return true;
}
std::unique_ptr<CXFA_TextLayout> m_pCapTextLayout;
std::unique_ptr<CXFA_TextProvider> m_pCapTextProvider;
std::unique_ptr<CFDE_TextOut> m_pTextOut;
std::vector<float> m_FieldSplitArray;
};
class CXFA_TextEditData final : public CXFA_FieldLayoutData {
public:
CXFA_TextEditData() = default;
~CXFA_TextEditData() override = default;
CXFA_TextEditData* AsTextEditData() override { return this; }
};
class CXFA_ImageEditData final : public CXFA_FieldLayoutData {
public:
CXFA_ImageEditData() = default;
~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->SetImageEditImage(XFA_LoadImageData(doc, image, m_bNamedImage,
m_iImageXDpi, m_iImageYDpi));
return !!m_pDIBitmap;
}
bool m_bNamedImage = false;
int32_t m_iImageXDpi = 0;
int32_t m_iImageYDpi = 0;
RetainPtr<CFX_DIBitmap> m_pDIBitmap;
};
CXFA_Node::CXFA_Node(CXFA_Document* pDoc,
XFA_PacketType ePacket,
uint32_t validPackets,
XFA_ObjectType oType,
XFA_Element eType,
pdfium::span<const PropertyData> properties,
pdfium::span<const AttributeData> attributes,
std::unique_ptr<CJX_Object> js_object)
: CXFA_Object(pDoc, oType, eType, std::move(js_object)),
m_Properties(properties),
m_Attributes(attributes),
m_ValidPackets(validPackets),
m_ePacket(ePacket) {
ASSERT(m_pDocument);
}
CXFA_Node::~CXFA_Node() = default;
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<CFX_XMLElement>(wsName);
WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value);
if (!wsValue.IsEmpty()) {
auto* text = GetXMLDocument()->CreateNode<CFX_XMLText>(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->SetFlagAndNotify(XFA_NodeFlag_Initialized);
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 {
return !!(m_ValidPackets & (1 << static_cast<uint8_t>(packet)));
}
const CXFA_Node::PropertyData* CXFA_Node::GetPropertyData(
XFA_Element property) const {
ASSERT(property != XFA_Element::Unknown);
for (const auto& prop : m_Properties) {
if (prop.property == property)
return &prop;
}
return nullptr;
}
bool CXFA_Node::HasProperty(XFA_Element property) const {
return !!GetPropertyData(property);
}
bool CXFA_Node::HasPropertyFlags(XFA_Element property, uint8_t flags) const {
const PropertyData* data = GetPropertyData(property);
return data && !!(data->flags & flags);
}
uint8_t CXFA_Node::PropertyOccuranceCount(XFA_Element property) const {
const PropertyData* data = GetPropertyData(property);
return data ? data->occurance_count : 0;
}
Optional<XFA_Element> CXFA_Node::GetFirstPropertyWithFlag(uint8_t flag) const {
for (const auto& prop : m_Properties) {
if (prop.flags & flag)
return prop.property;
}
return {};
}
const CXFA_Node::AttributeData* CXFA_Node::GetAttributeData(
XFA_Attribute attr) const {
ASSERT(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*> CXFA_Node::GetNodeListForType(XFA_Element eTypeFilter) {
std::vector<CXFA_Node*> nodes;
for (CXFA_Node* pChild = GetFirstChild(); pChild;
pChild = pChild->GetNextSibling()) {
if (pChild->GetElementType() == eTypeFilter)
nodes.push_back(pChild);
}
return nodes;
}
std::vector<CXFA_Node*> CXFA_Node::GetNodeListWithFilter(
uint32_t dwTypeFilter) {
std::vector<CXFA_Node*> nodes;
if (dwTypeFilter == (XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties)) {
for (CXFA_Node* pChild = GetFirstChild(); pChild;
pChild = pChild->GetNextSibling())
nodes.push_back(pChild);
return nodes;
}
if (dwTypeFilter == 0)
return nodes;
bool bFilterChildren = !!(dwTypeFilter & XFA_NODEFILTER_Children);
bool bFilterProperties = !!(dwTypeFilter & XFA_NODEFILTER_Properties);
bool bFilterOneOfProperties = !!(dwTypeFilter & XFA_NODEFILTER_OneOfProperty);
for (CXFA_Node* pChild = GetFirstChild(); pChild;
pChild = pChild->GetNextSibling()) {
if (HasProperty(pChild->GetElementType())) {
if (bFilterProperties) {
nodes.push_back(pChild);
} else if (bFilterOneOfProperties &&
HasPropertyFlags(pChild->GetElementType(),
XFA_PROPERTYFLAG_OneOf)) {
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;
Optional<XFA_Element> property =
GetFirstPropertyWithFlag(XFA_PROPERTYFLAG_DefaultOneOf);
if (!property.has_value())
return nodes;
CXFA_Node* pNewNode =
m_pDocument->CreateNode(GetPacketType(), property.value());
if (pNewNode) {
InsertChildAndNotify(pNewNode, nullptr);
pNewNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
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->SetFlagAndNotify(XFA_NodeFlag_Initialized);
return pNode;
}
CXFA_Node* CXFA_Node::CloneTemplateToForm(bool bRecursive) {
ASSERT(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->SetFlagAndNotify(XFA_NodeFlag_Initialized);
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() {
ASSERT(GetPacketType() == XFA_PacketType::Form);
return GetBindingNode();
}
int32_t CXFA_Node::AddBindItem(CXFA_Node* pFormNode) {
ASSERT(pFormNode);
if (BindsFormItems()) {
bool found = false;
for (auto* v : binding_nodes_) {
if (v == pFormNode) {
found = true;
break;
}
}
if (!found)
binding_nodes_.emplace_back(pFormNode);
return pdfium::CollectionSize<int32_t>(binding_nodes_);
}
CXFA_Node* pOldFormItem = GetBindingNode();
if (!pOldFormItem) {
SetBindingNode(pFormNode);
return 1;
}
if (pOldFormItem == pFormNode)
return 1;
std::vector<CXFA_Node*> items;
items.push_back(pOldFormItem);
items.push_back(pFormNode);
binding_nodes_ = std::move(items);
m_uNodeFlags |= XFA_NodeFlag_BindFormItems;
return 2;
}
int32_t 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 &= ~XFA_NodeFlag_BindFormItems;
return 1;
}
return pdfium::CollectionSize<int32_t>(binding_nodes_);
}
CXFA_Node* pOldFormItem = GetBindingNode();
if (pOldFormItem != pFormNode)
return pOldFormItem ? 1 : 0;
SetBindingNode(nullptr);
return 0;
}
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_DataBind);
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_DataBind);
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;
}
LocaleIface* CXFA_Node::GetLocale() {
Optional<WideString> localeName = GetLocaleName();
if (!localeName.has_value())
return nullptr;
if (localeName.value().EqualsASCII("ambient"))
return GetDocument()->GetLocaleMgr()->GetDefLocale();
return GetDocument()->GetLocaleMgr()->GetLocaleByName(localeName.value());
}
Optional<WideString> CXFA_Node::GetLocaleName() {
CXFA_Node* pForm = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form));
if (!pForm)
return {};
CXFA_Subform* pTopSubform =
pForm->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
if (!pTopSubform)
return {};
CXFA_Node* pLocaleNode = this;
do {
Optional<WideString> localeName =
pLocaleNode->JSObject()->TryCData(XFA_Attribute::Locale, false);
if (localeName)
return localeName;
pLocaleNode = pLocaleNode->GetParent();
} while (pLocaleNode && pLocaleNode != pTopSubform);
CXFA_Node* pConfig = ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Config));
WideString wsLocaleName =
GetDocument()->GetLocaleMgr()->GetConfigLocaleName(pConfig);
if (!wsLocaleName.IsEmpty())
return wsLocaleName;
if (pTopSubform) {
Optional<WideString> localeName =
pTopSubform->JSObject()->TryCData(XFA_Attribute::Locale, false);
if (localeName)
return localeName;
}
LocaleIface* pLocale = GetDocument()->GetLocaleMgr()->GetDefLocale();
if (!pLocale)
return {};
return pLocale->GetName();
}
XFA_AttributeValue CXFA_Node::GetIntact() {
CXFA_Keep* pKeep = GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep);
auto layout = JSObject()->TryEnum(XFA_Attribute::Layout, true);
XFA_AttributeValue eLayoutType =
layout.value_or(XFA_AttributeValue::Position);
if (pKeep) {
Optional<XFA_AttributeValue> intact = GetIntactFromKeep(pKeep, eLayoutType);
if (intact)
return *intact;
}
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) {
Optional<CXFA_Measurement> measureH =
JSObject()->TryMeasure(XFA_Attribute::H, false);
if (measureH)
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) {
ASSERT(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;
}
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_HasRemovedChildren);
InsertBefore(pNode, pBeforeNode);
CXFA_FFNotify* pNotify = m_pDocument->GetNotify();
if (pNotify)
pNotify->OnChildAdded(this);
if (!IsNeedSavingXMLNode() || !pNode->xml_node_)
return;
ASSERT(!pNode->xml_node_->GetParent());
xml_node_->InsertBefore(pNode->xml_node_.Get(),
pBeforeNode ? pBeforeNode->xml_node_.Get() : nullptr);
}
void CXFA_Node::RemoveChildAndNotify(CXFA_Node* pNode, bool bNotify) {
CHECK(pNode);
if (pNode->GetParent() != this)
return;
pNode->SetFlag(XFA_NodeFlag_HasRemovedChildren);
TreeNode<CXFA_Node>::RemoveChild(pNode);
OnRemoved(bNotify);
if (!IsNeedSavingXMLNode() || !pNode->xml_node_)
return;
if (!pNode->IsAttributeInXML()) {
xml_node_->RemoveChild(pNode->xml_node_.Get());
return;
}
ASSERT(pNode->xml_node_ == xml_node_);
CFX_XMLElement* pXMLElement = ToXMLElement(pNode->xml_node_.Get());
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<CFX_XMLElement>(wsName);
WideString wsValue = JSObject()->GetCData(XFA_Attribute::Value);
if (!wsValue.IsEmpty()) {
auto* text = GetXMLDocument()->CreateNode<CFX_XMLText>(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, false));
}
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, false));
}
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, false));
}
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*> CXFA_Node::GetSiblings(bool bIsClassName) {
std::vector<CXFA_Node*> 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();
TraverseSiblings(parent, dwNameHash, &siblings, bIsClassName, true);
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<CXFA_Node*> siblings;
TraverseSiblings(parent, dwHashName, &siblings, bIsClassIndex, true);
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.Right(wsInstName.GetLength() - 1) == wsName) {
pInstanceMgr = pNode;
}
break;
}
}
}
return pInstanceMgr;
}
CXFA_Occur* CXFA_Node::GetOccurIfExists() {
return GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
}
bool CXFA_Node::HasFlag(XFA_NodeFlag dwFlag) const {
if (m_uNodeFlags & dwFlag)
return true;
if (dwFlag == XFA_NodeFlag_HasRemovedChildren)
return GetParent() && GetParent()->HasFlag(dwFlag);
return false;
}
void CXFA_Node::SetFlagAndNotify(uint32_t dwFlag) {
ASSERT(dwFlag == XFA_NodeFlag_Initialized);
if (!IsInitialized()) {
CXFA_FFNotify* pNotify = m_pDocument->GetNotify();
if (pNotify) {
pNotify->OnNodeReady(this);
}
}
m_uNodeFlags |= dwFlag;
}
void CXFA_Node::SetFlag(uint32_t dwFlag) {
m_uNodeFlags |= dwFlag;
}
void CXFA_Node::ClearFlag(uint32_t dwFlag) {
m_uNodeFlags &= ~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(), false);
}
CFX_XMLNode* CXFA_Node::CreateXMLMappingNode() {
if (!xml_node_) {
xml_node_ = GetXMLDocument()->CreateNode<CFX_XMLElement>(
JSObject()->GetCData(XFA_Attribute::Name));
}
return xml_node_.Get();
}
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.Right(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.Right(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) {
std::set<CXFA_Node*> sNew;
std::set<CXFA_Node*> sAfter;
CXFA_NodeIteratorTemplate<CXFA_Node,
CXFA_TraverseStrategy_XFAContainerNode>
sIteratorNew(pNewInstance);
for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode;
pNode = sIteratorNew.MoveToNext()) {
CXFA_Node* pDataNode = pNode->GetBindData();
if (!pDataNode)
continue;
sNew.insert(pDataNode);
}
CXFA_NodeIteratorTemplate<CXFA_Node,
CXFA_TraverseStrategy_XFAContainerNode>
sIteratorAfter(pNextSibling);
for (CXFA_Node* pNode = sIteratorAfter.GetCurrent(); pNode;
pNode = sIteratorAfter.MoveToNext()) {
CXFA_Node* pDataNode = pNode->GetBindData();
if (!pDataNode)
continue;
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) {
std::set<CXFA_Node*> sNew;
std::set<CXFA_Node*> sBefore;
CXFA_NodeIteratorTemplate<CXFA_Node,
CXFA_TraverseStrategy_XFAContainerNode>
sIteratorNew(pNewInstance);
for (CXFA_Node* pNode = sIteratorNew.GetCurrent(); pNode;
pNode = sIteratorNew.MoveToNext()) {
CXFA_Node* pDataNode = pNode->GetBindData();
if (!pDataNode)
continue;
sNew.insert(pDataNode);
}
CXFA_NodeIteratorTemplate<CXFA_Node,
CXFA_TraverseStrategy_XFAContainerNode>
sIteratorBefore(pBeforeInstance);
for (CXFA_Node* pNode = sIteratorBefore.GetCurrent(); pNode;
pNode = sIteratorBefore.MoveToNext()) {
CXFA_Node* pDataNode = pNode->GetBindData();
if (!pDataNode)
continue;
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<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
sIterator(pRemoveInstance);
for (CXFA_Node* pFormNode = sIterator.GetCurrent(); pFormNode;
pFormNode = sIterator.MoveToNext()) {
CXFA_Node* pDataNode = pFormNode->GetBindData();
if (!pDataNode)
continue;
if (pDataNode->RemoveBindItem(pFormNode) == 0) {
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));
ASSERT(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;
}
Optional<bool> CXFA_Node::GetDefaultBoolean(XFA_Attribute attr) const {
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Boolean);
if (!value)
return {};
return {!!*value};
}
Optional<int32_t> CXFA_Node::GetDefaultInteger(XFA_Attribute attr) const {
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Integer);
if (!value)
return {};
return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(*value))};
}
Optional<CXFA_Measurement> CXFA_Node::GetDefaultMeasurement(
XFA_Attribute attr) const {
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Measure);
if (!value)
return {};
WideString str = WideString(static_cast<const wchar_t*>(*value));
return {CXFA_Measurement(str.AsStringView())};
}
Optional<WideString> CXFA_Node::GetDefaultCData(XFA_Attribute attr) const {
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::CData);
if (!value)
return {};
return {WideString(static_cast<const wchar_t*>(*value))};
}
Optional<XFA_AttributeValue> CXFA_Node::GetDefaultEnum(
XFA_Attribute attr) const {
Optional<void*> value = GetDefaultValue(attr, XFA_AttributeType::Enum);
if (!value)
return {};
return {static_cast<XFA_AttributeValue>(reinterpret_cast<uintptr_t>(*value))};
}
Optional<void*> CXFA_Node::GetDefaultValue(XFA_Attribute attr,
XFA_AttributeType eType) const {
const AttributeData* data = GetAttributeData(attr);
if (!data)
return {};
if (data->type == eType)
return {data->default_value};
return {};
}
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(this);
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(pParent);
}
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() {
return JSObject()->GetContent(false);
}
int32_t CXFA_Node::GetRotate() const {
Optional<int32_t> degrees =
JSObject()->TryInteger(XFA_Attribute::Rotate, false);
return degrees ? XFA_MapRotation(*degrees) / 90 * 90 : 0;
}
CXFA_Border* CXFA_Node::GetBorderIfExists() const {
return JSObject()->GetProperty<CXFA_Border>(0, XFA_Element::Border);
}
CXFA_Border* CXFA_Node::GetOrCreateBorderIfPossible() {
return JSObject()->GetOrCreateProperty<CXFA_Border>(0, XFA_Element::Border);
}
CXFA_Caption* CXFA_Node::GetCaptionIfExists() const {
return JSObject()->GetProperty<CXFA_Caption>(0, XFA_Element::Caption);
}
CXFA_Font* CXFA_Node::GetOrCreateFontIfPossible() {
return JSObject()->GetOrCreateProperty<CXFA_Font>(0, XFA_Element::Font);
}
CXFA_Font* CXFA_Node::GetFontIfExists() const {
return JSObject()->GetProperty<CXFA_Font>(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<CXFA_Margin>(0, XFA_Element::Margin);
}
CXFA_Para* CXFA_Node::GetParaIfExists() const {
return JSObject()->GetProperty<CXFA_Para>(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<CXFA_Value>(
0, XFA_Element::Value)
: nullptr;
}
CXFA_Value* CXFA_Node::GetFormValueIfExists() const {
return JSObject()->GetProperty<CXFA_Value>(0, XFA_Element::Value);
}
CXFA_Calculate* CXFA_Node::GetCalculateIfExists() const {
return JSObject()->GetProperty<CXFA_Calculate>(0, XFA_Element::Calculate);
}
CXFA_Validate* CXFA_Node::GetValidateIfExists() const {
return JSObject()->GetProperty<CXFA_Validate>(0, XFA_Element::Validate);
}
CXFA_Validate* CXFA_Node::GetOrCreateValidateIfPossible() {
return JSObject()->GetOrCreateProperty<CXFA_Validate>(0,
XFA_Element::Validate);
}
CXFA_Bind* CXFA_Node::GetBindIfExists() const {
return JSObject()->GetProperty<CXFA_Bind>(0, XFA_Element::Bind);
}
Optional<XFA_AttributeValue> CXFA_Node::GetIntactFromKeep(
const CXFA_Keep* pKeep,
XFA_AttributeValue eLayoutType) const {
Optional<XFA_AttributeValue> intact =
pKeep->JSObject()->TryEnum(XFA_Attribute::Intact, false);
if (!intact.has_value())
return {};
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;
}
Optional<XFA_AttributeValue> value =
pKeep->JSObject()->TryEnum(XFA_Attribute::Previous, false);
if (value && (*value == XFA_AttributeValue::ContentArea ||
*value == XFA_AttributeValue::PageArea)) {
return XFA_AttributeValue::ContentArea;
}
CXFA_Keep* pNode =
pPreviewRow->GetFirstChildByClass<CXFA_Keep>(XFA_Element::Keep);
if (!pNode)
return intact;
Optional<XFA_AttributeValue> ret =
pNode->JSObject()->TryEnum(XFA_Attribute::Next, false);
if (!ret)
return intact;
return (*ret == XFA_AttributeValue::ContentArea ||
*ret == XFA_AttributeValue::PageArea)
? XFA_AttributeValue::ContentArea
: intact;
}
Optional<float> CXFA_Node::TryWidth() {
return JSObject()->TryMeasureAsFloat(XFA_Attribute::W);
}
Optional<float> CXFA_Node::TryHeight() {
return JSObject()->TryMeasureAsFloat(XFA_Attribute::H);
}
Optional<float> CXFA_Node::TryMinWidth() {
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinW);
}
Optional<float> CXFA_Node::TryMinHeight() {
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MinH);
}
Optional<float> CXFA_Node::TryMaxWidth() {
return JSObject()->TryMeasureAsFloat(XFA_Attribute::MaxW);
}
Optional<float> 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<CXFA_Event*> 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;
XFA_EventError iRet =
ExecuteScript(pDocView, calc->GetScriptIfExists(), &EventParam);
if (iRet != XFA_EventError::kSuccess)
return iRet;
if (GetRawValue() != EventParam.m_wsResult) {
SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult);
UpdateUIDisplay(pDocView, nullptr);
}
return XFA_EventError::kSuccess;
}
void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* pDocView,
CXFA_Validate* validate,
XFA_EventError iRet,
bool bRetValue,
bool bVersionFlag) {
if (iRet != XFA_EventError::kSuccess)
return;
if (bRetValue)
return;
IXFA_AppProvider* 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<uint32_t>(AlertIcon::kWarning),
static_cast<uint32_t>(AlertButton::kOK));
return;
}
if (pAppProvider->MsgBox(wsScriptMsg, wsTitle,
static_cast<uint32_t>(AlertIcon::kWarning),
static_cast<uint32_t>(AlertButton::kYesNo)) ==
static_cast<uint32_t>(AlertReturn::kYes)) {
SetFlag(XFA_NodeFlag_UserInteractive);
}
return;
}
if (wsScriptMsg.IsEmpty())
wsScriptMsg = GetValidateMessage(true, bVersionFlag);
pAppProvider->MsgBox(wsScriptMsg, wsTitle,
static_cast<uint32_t>(AlertIcon::kError),
static_cast<uint32_t>(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;
LocaleIface* 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;
IXFA_AppProvider* 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<uint32_t>(AlertIcon::kError),
static_cast<uint32_t>(AlertButton::kOK));
return XFA_EventError::kError;
}
if (wsFormatMsg.IsEmpty())
wsFormatMsg = GetValidateMessage(false, bVersionFlag);
if (bVersionFlag) {
pAppProvider->MsgBox(wsFormatMsg, wsTitle,
static_cast<uint32_t>(AlertIcon::kWarning),
static_cast<uint32_t>(AlertButton::kOK));
return XFA_EventError::kError;
}
if (pAppProvider->MsgBox(wsFormatMsg, wsTitle,
static_cast<uint32_t>(AlertIcon::kWarning),
static_cast<uint32_t>(AlertButton::kYesNo)) ==
static_cast<uint32_t>(AlertReturn::kYes)) {
SetFlag(XFA_NodeFlag_UserInteractive);
}
return XFA_EventError::kError;
}
XFA_EventError CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* pDocView,
CXFA_Validate* validate,
int32_t iFlags,
bool bVersionFlag) {
if (!GetValue(XFA_VALUEPICTURE_Raw).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) {
XFA_EventError iRet = XFA_EventError::kSuccess;
if (eNullTest != XFA_AttributeValue::Disabled)
iRet = XFA_EventError::kError;
if (wsNullMsg.IsEmpty())
return iRet;
if (eNullTest != XFA_AttributeValue::Disabled) {
pDocView->m_arrNullTestMsg.push_back(wsNullMsg);
return XFA_EventError::kError;
}
return XFA_EventError::kSuccess;
}
if (wsNullMsg.IsEmpty() && bVersionFlag &&
eNullTest != XFA_AttributeValue::Disabled) {
return XFA_EventError::kError;
}
IXFA_AppProvider* 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<uint32_t>(AlertIcon::kStatus),
static_cast<uint32_t>(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<uint32_t>(AlertIcon::kWarning),
static_cast<uint32_t>(AlertButton::kYesNo)) ==
static_cast<uint32_t>(AlertReturn::kYes)) {
SetFlag(XFA_NodeFlag_UserInteractive);
}
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;
bool bInitDoc = validate->NeedsInitApp();
bool bStatus = pDocView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
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;
eParam.m_pTarget = this;
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_NeedsInitApp);
} else {
iFormat = ProcessFormatTestValidate(pDocView, validate, bVersionFlag);
if (!bVersionFlag)
bVersionFlag = pDocView->GetDoc()->GetXFADoc()->is_scripting();
XFA_EventErrorAccumulate(
&iRet,
ProcessNullTestValidate(pDocView, validate, iFlags, bVersionFlag));
}
if (iFormat != XFA_EventError::kSuccess && hasBoolResult)
ProcessScriptTestValidate(pDocView, validate, iRet, bRet, 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<XFA_EventError, bool> CXFA_Node::ExecuteBoolScript(
CXFA_FFDocView* pDocView,
CXFA_Script* script,
CXFA_EventParam* pEventParam) {
if (m_ExecuteRecursionDepth > kMaxExecuteRecursion)
return {XFA_EventError::kSuccess, false};
ASSERT(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();
pContext->SetEventParam(pEventParam);
pContext->SetRunAtType(script->GetRunAt());
std::vector<CXFA_Node*> refNodes;
if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
pEventParam->m_eType == XFA_EVENT_Calculate) {
pContext->SetNodesOfRunScript(&refNodes);
}
auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate());
bool bRet = false;
{
AutoRestorer<uint8_t> 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()) {
if (!pTmpRetValue->IsNull())
pEventParam->m_wsResult = pTmpRetValue->ToWideString();
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_Raw, pEventParam->m_wsResult);
pDocView->AddValidateNode(this);
}
}
for (CXFA_Node* pRefNode : refNodes) {
if (pRefNode == this)
continue;
CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData();
if (!pGlobalData) {
pRefNode->JSObject()->SetCalcData(
pdfium::MakeUnique<CXFA_CalcData>());
pGlobalData = pRefNode->JSObject()->GetCalcData();
}
if (!pdfium::ContainsValue(pGlobalData->m_Globals, this))
pGlobalData->m_Globals.push_back(this);
}
}
}
pContext->SetNodesOfRunScript(nullptr);
pContext->SetEventParam(nullptr);
return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false};
}
std::pair<XFA_FFWidgetType, CXFA_Ui*>
CXFA_Node::CreateChildUIAndValueNodesIfNeeded() {
XFA_Element eType = GetElementType();
ASSERT(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<CXFA_Ui>(0, XFA_Element::Ui);
ASSERT(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<CXFA_Value>(0, XFA_Element::Value);
ASSERT(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:
NOTREACHED();
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();
}
if (!pUIChild) {
if (expected_ui_child_type == XFA_Element::Unknown)
expected_ui_child_type = XFA_Element::TextEdit;
pUIChild = pUI->JSObject()->GetOrCreateProperty<CXFA_Node>(
0, expected_ui_child_type);
}
CreateValueNodeIfNeeded(value, pUIChild);
return {widget_type, pUI};
}
XFA_FFWidgetType CXFA_Node::GetDefaultFFWidgetType() const {
NOTREACHED();
return XFA_FFWidgetType::kNone;
}
CXFA_Node* CXFA_Node::CreateUINodeIfNeeded(CXFA_Ui* ui, XFA_Element type) {
return ui->JSObject()->GetOrCreateProperty<CXFA_Node>(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<CXFA_Items>(0, XFA_Element::Items, false);
if (pItems) {
CXFA_Node* pItem =
pItems->GetChild<CXFA_Node>(0, XFA_Element::Unknown, false);
if (pItem)
valueType = pItem->GetElementType();
}
}
value->JSObject()->GetOrCreateProperty<CXFA_Node>(0, valueType);
}
XFA_Element CXFA_Node::GetValueNodeType() const {
return XFA_Element::Text;
}
CXFA_Node* CXFA_Node::GetUIChildNode() {
ASSERT(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();
}
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<CXFA_Border>(
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<CXFA_Margin>(0, XFA_Element::Margin);
if (!mgUI)
return CFX_RectF();
CXFA_Border* border = GetUIBorder();
if (border && border->GetPresence() != XFA_AttributeValue::Visible)
return CFX_RectF();
Optional<float> left = mgUI->TryLeftInset();
Optional<float> top = mgUI->TryTopInset();
Optional<float> right = mgUI->TryRightInset();
Optional<float> 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 || !top || !right || !bottom) {
std::vector<CXFA_Stroke*> strokes = border->GetStrokes();
if (!top)
top = GetEdgeThickness(strokes, bVisible, 0);
if (!right)
right = GetEdgeThickness(strokes, bVisible, 1);
if (!bottom)
bottom = GetEdgeThickness(strokes, bVisible, 2);
if (!left)
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_Event*> CXFA_Node::GetEventByActivity(
XFA_AttributeValue iActivity,
bool bIsFormReady) {
std::vector<CXFA_Event*> events;
for (CXFA_Node* node : GetNodeListForType(XFA_Element::Event)) {
auto* event = static_cast<CXFA_Event*>(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_Raw, wsValue);
pChild->SetValue(XFA_VALUEPICTURE_Raw, wsValue);
done = true;
}
}
if (!done) {
CXFA_Items* pItems =
pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
if (!pItems)
continue;
WideString itemText;
if (pItems->CountChildren(XFA_Element::Unknown, false) > 1) {
itemText =
pItems->GetChild<CXFA_Node>(1, XFA_Element::Unknown, false)
->JSObject()
->GetContent(false);
}
pChild->SetValue(XFA_VALUEPICTURE_Raw, itemText);
}
pNextChild = pChild->GetNextContainerSibling();
}
break;
}
case XFA_FFWidgetType::kChoiceList:
ClearAllSelections();
FALLTHROUGH;
default: {
CXFA_Value* defValue = GetDefaultValueIfExists();
if (defValue)
wsValue = defValue->GetChildValueContent();
SetValue(XFA_VALUEPICTURE_Raw, 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, false,
false);
CXFA_Node* pHrefNode = pBind->GetFirstChild();
if (pHrefNode) {
pHrefNode->JSObject()->SetCData(XFA_Attribute::Value, wsHref, false, false);
return;
}
CFX_XMLElement* pElement = ToXMLElement(pBind->GetXMLMappingNode());
pElement->SetAttribute(L"href", wsHref);
}
CXFA_FFWidget* CXFA_Node::GetNextWidget(CXFA_FFWidget* pWidget) {
return GetFFWidget(pWidget->GetLayoutItem()->GetNext());
}
void CXFA_Node::UpdateUIDisplay(CXFA_FFDocView* pDocView,
CXFA_FFWidget* pExcept) {
CXFA_FFWidget* pWidget = pDocView->GetWidgetForNode(this);
for (; pWidget; pWidget = GetNextWidget(pWidget)) {
if (pWidget == pExcept || !pWidget->IsLoaded() ||
(GetFFWidgetType() != XFA_FFWidgetType::kCheckButton &&
pWidget->IsFocused())) {
continue;
}
pWidget->UpdateFWLData();
pWidget->InvalidateRect();
}
}
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.get();
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();
Optional<float> width = TryWidth();
if (width) {
pSize->width = *width;
} else {
Optional<float> min = TryMinWidth();
if (min)
pSize->width = std::max(pSize->width, *min);
Optional<float> max = TryMaxWidth();
if (max && *max > 0)
pSize->width = std::min(pSize->width, *max);
}
Optional<float> height = TryHeight();
if (height) {
pSize->height = *height;
} else {
Optional<float> min = TryMinHeight();
if (min)
pSize->height = std::max(pSize->height, *min);
Optional<float> max = TryMaxHeight();
if (max && *max > 0)
pSize->height = std::min(pSize->height, *max);
}
return true;
}
void CXFA_Node::CalculateTextContentSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
float fFontSize = GetFontSize();
WideString wsText = GetValue(XFA_VALUEPICTURE_Display);
if (wsText.IsEmpty()) {
pSize->height += fFontSize;
return;
}
wchar_t wcEnter = '\n';
wchar_t wsLast = wsText[wsText.GetLength() - 1];
if (wsLast == wcEnter)
wsText = wsText + wcEnter;
CXFA_FieldLayoutData* layoutData = m_pLayoutData->AsFieldLayoutData();
if (!layoutData->m_pTextOut) {
layoutData->m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>();
CFDE_TextOut* pTextOut = layoutData->m_pTextOut.get();
pTextOut->SetFont(GetFDEFont(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, 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;
Optional<float> width = TryWidth();
if (width) {
rtFit.width = *width;
GetWidthWithoutMargin(rtFit.width);
} else {
rtFit.width = rtImage.width;
}
Optional<float> height = TryHeight();
if (height) {
rtFit.height = *height;
GetHeightWithoutMargin(rtFit.height);
} else {
rtFit.height = rtImage.height;
}
return rtFit.Size();
}
bool CXFA_Node::CalculateImageAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
if (!GetImageImage())
LoadImageImage(doc);
pSize->clear();
RetainPtr<CFX_DIBitmap> pBitmap = GetImageImage();
if (!pBitmap)
return CalculateWidgetAutoSize(pSize);
*pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(),
GetImageDpi());
return CalculateWidgetAutoSize(pSize);
}
bool CXFA_Node::CalculateImageEditAutoSize(CXFA_FFDoc* doc, CFX_SizeF* pSize) {
if (!GetImageEditImage())
LoadImageEditImage(doc);
pSize->clear();
RetainPtr<CFX_DIBitmap> pBitmap = GetImageEditImage();
if (!pBitmap)
return CalculateFieldAutoSize(doc, pSize);
*pSize = CalculateImageSize(pBitmap->GetWidth(), pBitmap->GetHeight(),
GetImageEditDpi());
return CalculateFieldAutoSize(doc, pSize);
}
bool CXFA_Node::LoadImageImage(CXFA_FFDoc* doc) {
InitLayoutData();
return m_pLayoutData->AsImageLayoutData()->LoadImageData(doc, this);
}
bool CXFA_Node::LoadImageEditImage(CXFA_FFDoc* doc) {
InitLayoutData();
return m_pLayoutData->AsFieldLayoutData()->AsImageEditData()->LoadImageData(
doc, this);
}
CFX_Size CXFA_Node::GetImageDpi() const {
CXFA_ImageLayoutData* pData = m_pLayoutData->AsImageLayoutData();
return CFX_Size(pData->m_iImageXDpi, pData->m_iImageYDpi);
}
CFX_Size CXFA_Node::GetImageEditDpi() const {
CXFA_ImageEditData* pData =
m_pLayoutData->AsFieldLayoutData()->AsImageEditData();
return CFX_Size(pData->m_iImageXDpi, pData->m_iImageYDpi);
}
float CXFA_Node::CalculateWidgetAutoWidth(float fWidthCalc) {
CXFA_Margin* margin = GetMarginIfExists();
if (margin)
fWidthCalc += margin->GetLeftInset() + margin->GetRightInset();
Optional<float> min = TryMinWidth();
if (min)
fWidthCalc = std::max(fWidthCalc, *min);
Optional<float> max = TryMaxWidth();
if (max && *max > 0)
fWidthCalc = std::min(fWidthCalc, *max);
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();
Optional<float> min = TryMinHeight();
if (min)
fHeightCalc = std::max(fHeightCalc, *min);
Optional<float> max = TryMaxHeight();
if (max && *max > 0)
fHeightCalc = std::min(fHeightCalc, *max);
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();
if (GetFFWidgetType() == XFA_FFWidgetType::kText) {
m_pLayoutData->m_fWidgetHeight = TryHeight().value_or(-1);
StartTextLayout(doc, pCalcWidth, pCalcHeight);
return;
}
if (*pCalcWidth > 0 && *pCalcHeight > 0)
return;
m_pLayoutData->m_fWidgetHeight = -1;
float fWidth = 0;
if (*pCalcWidth > 0 && *pCalcHeight < 0) {
Optional<float> height = TryHeight();
if (height) {
*pCalcHeight = *height;
} else {
CFX_SizeF size = CalculateAccWidthAndHeight(doc, *pCalcWidth);
*pCalcWidth = size.width;
*pCalcHeight = size.height;
}
m_pLayoutData->m_fWidgetHeight = *pCalcHeight;
return;
}
if (*pCalcWidth < 0 && *pCalcHeight < 0) {
Optional<float> height;
Optional<float> width = TryWidth();
if (width) {
fWidth = *width;
height = TryHeight();
if (height)
*pCalcHeight = *height;
}
if (!width || !height) {
CFX_SizeF size = CalculateAccWidthAndHeight(doc, fWidth);
*pCalcWidth = size.width;
*pCalcHeight = size.height;
} else {
*pCalcWidth = fWidth;
}
}
m_pLayoutData->m_fWidgetHeight = *pCalcHeight;
}
CFX_SizeF CXFA_Node::CalculateAccWidthAndHeight(CXFA_FFDoc* doc, float fWidth) {
CFX_SizeF sz(fWidth, m_pLayoutData->m_fWidgetHeight);
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->m_fWidgetHeight = sz.height;
return sz;
}
Optional<float> CXFA_Node::FindSplitPos(CXFA_FFDocView* pDocView,
size_t szBlockIndex,
float fCalcHeight) {
if (GetFFWidgetType() == XFA_FFWidgetType::kSubform)
return pdfium::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->m_fWidgetHeight - fTopInset);
if (fCalcHeight != 0) {
if (szBlockIndex == 0)
fCalcHeight += fTopInset;
if (fabs(fHeight - fCalcHeight) < kXFAWidgetPrecision)
return pdfium::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->m_fWidgetHeight - 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->m_fWidgetHeight;
if (GetValue(XFA_VALUEPICTURE_Display).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<float>* pFieldArray = &pFieldData->m_FieldSplitArray;
size_t szFieldSplitCount = pFieldArray->size();
if (szFieldSplitCount < szBlockIndex * 3)
return pdfium::nullopt;
for (size_t i = 0; i < szBlockIndex * 3; i += 3) {
iLinesCount -= (int32_t)(*pFieldArray)[i + 1];
fHeight -= (*pFieldArray)[i + 2];
}
if (iLinesCount == 0)
return pdfium::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();
break;
}
}
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 pdfium::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 =
(int32_t)((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 pdfium::nullopt;
}
if (fHeight - fStartOffset - fTextHeight < fFontSize) {
iLineNum -= 1;
if (iLineNum == 0)
return 0.0f;
} else {
iLineNum = (int32_t)(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 pdfium::nullopt;
return fSplitHeight;
}
void CXFA_Node::InitLayoutData() {
if (m_pLayoutData)
return;
switch (GetFFWidgetType()) {
case XFA_FFWidgetType::kText:
m_pLayoutData = pdfium::MakeUnique<CXFA_TextLayoutData>();
return;
case XFA_FFWidgetType::kTextEdit:
m_pLayoutData = pdfium::MakeUnique<CXFA_TextEditData>();
return;
case XFA_FFWidgetType::kImage:
m_pLayoutData = pdfium::MakeUnique<CXFA_ImageLayoutData>();
return;
case XFA_FFWidgetType::kImageEdit:
m_pLayoutData = pdfium::MakeUnique<CXFA_ImageEditData>();
return;
default:
break;
}
if (GetElementType() == XFA_Element::Field) {
m_pLayoutData = pdfium::MakeUnique<CXFA_FieldLayoutData>();
return;
}
m_pLayoutData = pdfium::MakeUnique<CXFA_WidgetLayoutData>();
}
void CXFA_Node::StartTextLayout(CXFA_FFDoc* doc,
float* pCalcWidth,
float* pCalcHeight) {
InitLayoutData();
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) {
Optional<float> width = TryWidth();
if (width) {
pTextLayout->StartLayout(GetWidthWithoutMargin(*width));
*pCalcWidth = *width;
} else {
float fMaxWidth = CalculateWidgetAutoWidth(pTextLayout->StartLayout(-1));
pTextLayout->StartLayout(GetWidthWithoutMargin(fMaxWidth));
*pCalcWidth = fMaxWidth;
}
}
if (m_pLayoutData->m_fWidgetHeight < 0) {
m_pLayoutData->m_fWidgetHeight = pTextLayout->GetLayoutHeight();
m_pLayoutData->m_fWidgetHeight =
CalculateWidgetAutoHeight(m_pLayoutData->m_fWidgetHeight);
}
fTextHeight = m_pLayoutData->m_fWidgetHeight;
fTextHeight = GetHeightWithoutMargin(fTextHeight);
pTextLayout->DoLayout(fTextHeight);
*pCalcHeight = m_pLayoutData->m_fWidgetHeight;
}
bool CXFA_Node::LoadCaption(CXFA_FFDoc* doc) {
InitLayoutData();
return m_pLayoutData->AsFieldLayoutData()->LoadCaption(doc, this);
}
CXFA_TextLayout* CXFA_Node::GetCaptionTextLayout() {
return m_pLayoutData
? m_pLayoutData->AsFieldLayoutData()->m_pCapTextLayout.get()
: nullptr;
}
CXFA_TextLayout* CXFA_Node::GetTextLayout() {
return m_pLayoutData ? m_pLayoutData->AsTextLayoutData()->GetTextLayout()
: nullptr;
}
RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageImage() {
return m_pLayoutData ? m_pLayoutData->AsImageLayoutData()->m_pDIBitmap
: nullptr;
}
RetainPtr<CFX_DIBitmap> CXFA_Node::GetImageEditImage() {
return m_pLayoutData ? m_pLayoutData->AsFieldLayoutData()
->AsImageEditData()
->m_pDIBitmap
: nullptr;
}
void CXFA_Node::SetImageImage(const RetainPtr<CFX_DIBitmap>& newImage) {
CXFA_ImageLayoutData* pData = m_pLayoutData->AsImageLayoutData();
if (pData->m_pDIBitmap != newImage)
pData->m_pDIBitmap = newImage;
}
void CXFA_Node::SetImageEditImage(const RetainPtr<CFX_DIBitmap>& newImage) {
CXFA_ImageEditData* pData =
m_pLayoutData->AsFieldLayoutData()->AsImageEditData();
if (pData->m_pDIBitmap != newImage)
pData->m_pDIBitmap = newImage;
}
RetainPtr<CFGAS_GEFont> CXFA_Node::GetFDEFont(CXFA_FFDoc* doc) {
WideString wsFontName = L"Courier";
uint32_t dwFontStyle = 0;
CXFA_Font* font = GetFontIfExists();
if (font) {
if (font->IsBold())
dwFontStyle |= FXFONT_BOLD;
if (font->IsItalic())
dwFontStyle |= FXFONT_ITALIC;
wsFontName = font->GetTypeface();
}
return doc->GetApp()->GetXFAFontMgr()->GetFont(doc, wsFontName.AsStringView(),
dwFontStyle);
}
bool CXFA_Node::HasButtonRollover() {
CXFA_Items* pItems = GetChild<CXFA_Items>(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() {
CXFA_Items* pItems = GetChild<CXFA_Items>(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_Off;
auto* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
if (!pItems)
return XFA_CHECKSTATE_Off;
CXFA_Node* pText = pItems->GetFirstChild();
int32_t i = 0;
while (pText) {
Optional<WideString> wsContent = pText->JSObject()->TryContent(false, true);
if (wsContent && *wsContent == wsValue)
return static_cast<XFA_CHECKSTATE>(i);
i++;
pText = pText->GetNextSibling();
}
return XFA_CHECKSTATE_Off;
}
void CXFA_Node::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) {
CXFA_Node* node = GetExclGroupIfExists();
if (!node) {
CXFA_Items* pItems = GetChild<CXFA_Items>(0, XFA_Element::Items, false);
if (!pItems)
return;
int32_t i = -1;
CXFA_Node* pText = pItems->GetFirstChild();
WideString wsContent;
while (pText) {
i++;
if (i == eCheckState) {
wsContent = pText->JSObject()->GetContent(false);
break;
}
pText = pText->GetNextSibling();
}
SyncValue(wsContent, bNotify);
return;
}
WideString wsValue;
if (eCheckState != XFA_CHECKSTATE_Off) {
if (CXFA_Items* pItems =
GetChild<CXFA_Items>(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<CXFA_Items>(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, bNotify);
}
node->SyncValue(wsValue, bNotify);
}
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_On) {
pSelectedMember = pNode;
break;
}
}
return pSelectedMember;
}
CXFA_Node* CXFA_Node::SetSelectedMember(WideStringView wsName, bool bNotify) {
uint32_t nameHash = FX_HashCode_GetW(wsName, false);
for (CXFA_Node* pNode = ToNode(GetFirstChild()); pNode;
pNode = pNode->GetNextSibling()) {
if (pNode->GetNameHash() == nameHash) {
pNode->SetCheckState(XFA_CHECKSTATE_On, bNotify);
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<CXFA_Items>(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;
}
int32_t CXFA_Node::CountChoiceListItems(bool bSaveValue) {
std::vector<CXFA_Node*> 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);
}
Optional<WideString> CXFA_Node::GetChoiceListItem(int32_t nIndex,
bool bSaveValue) {
std::vector<CXFA_Node*> 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 {};
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 {};
CXFA_Node* pItem =
pItems->GetChild<CXFA_Node>(nIndex, XFA_Element::Unknown, false);
if (pItem)
return {pItem->JSObject()->GetContent(false)};
return {};
}
std::vector<WideString> CXFA_Node::GetChoiceListItems(bool bSaveValue) {
std::vector<CXFA_Node*> 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<WideString>();
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<WideString> 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<WideString> wsValueArray = GetSelectedItemsValue();
if (IsListBox() || !IsChoiceListAllowTextEntry())
return pdfium::CollectionSize<int32_t>(wsValueArray);
int32_t iSelected = 0;
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
for (const auto& value : wsValueArray) {
if (pdfium::ContainsValue(wsSaveTextArray, value))
iSelected++;
}
return iSelected;
}
int32_t CXFA_Node::GetSelectedItem(int32_t nIndex) {
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
if (!pdfium::IndexInBounds(wsValueArray, nIndex))
return -1;
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(),
wsValueArray[nIndex]);
return it != wsSaveTextArray.end() ? it - wsSaveTextArray.begin() : -1;
}
std::vector<int32_t> CXFA_Node::GetSelectedItems() {
std::vector<int32_t> iSelArray;
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
for (const auto& value : wsValueArray) {
auto it = std::find(wsSaveTextArray.begin(), wsSaveTextArray.end(), value);
if (it != wsSaveTextArray.end())
iSelArray.push_back(it - wsSaveTextArray.begin());
}
return iSelArray;
}
std::vector<WideString> CXFA_Node::GetSelectedItemsValue() {
WideString wsValue = GetRawValue();
if (IsChoiceListMultiSelect())
return fxcrt::Split(wsValue, L'\n');
std::vector<WideString> wsSelTextArray;
wsSelTextArray.push_back(wsValue);
return wsSelTextArray;
}
bool CXFA_Node::GetItemState(int32_t nIndex) {
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
return pdfium::IndexInBounds(wsSaveTextArray, nIndex) &&
pdfium::ContainsValue(GetSelectedItemsValue(),
wsSaveTextArray[nIndex]);
}
void CXFA_Node::SetItemState(int32_t nIndex,
bool bSelected,
bool bNotify,
bool bScriptModify,
bool bSyncData) {
std::vector<WideString> wsSaveTextArray = GetChoiceListItems(true);
if (!pdfium::IndexInBounds(wsSaveTextArray, nIndex))
return;
int32_t iSel = -1;
std::vector<WideString> wsValueArray = GetSelectedItemsValue();
auto value_iter = std::find(wsValueArray.begin(), wsValueArray.end(),
wsSaveTextArray[nIndex]);
if (value_iter != wsValueArray.end())
iSel = 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,
bSyncData);
}
} else if (iSel >= 0) {
std::vector<int32_t> 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, bSyncData);
}
} else {
if (bSelected) {
if (iSel < 0) {
WideString wsSaveText = wsSaveTextArray[nIndex];
JSObject()->SetContent(wsSaveText, GetFormatDataValue(wsSaveText),
bNotify, bScriptModify, bSyncData);
}
} else if (iSel >= 0) {
JSObject()->SetContent(WideString(), WideString(), bNotify, bScriptModify,
bSyncData);
}
}
}
void CXFA_Node::SetSelectedItems(const std::vector<int32_t>& iSelArray,
bool bNotify,
bool bScriptModify,
bool bSyncData) {
WideString wsValue;
int32_t iSize = pdfium::CollectionSize<int32_t>(iSelArray);
if (iSize >= 1) {
std::vector<WideString> 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<CXFA_Node*> 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)
return;
GetDocument()->GetNotify()->OnWidgetListItemAdded(this, wsLabel.c_str(),
wsValue.c_str(), nIndex);
}
WideString CXFA_Node::GetItemLabel(WideStringView wsValue) const {
std::vector<CXFA_Node*> 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<CXFA_Node>(iSearch, XFA_Element::Unknown, false);
return pText ? pText->JSObject()->GetContent(false) : WideString();
}
WideString CXFA_Node::GetItemValue(WideStringView wsLabel) {
int32_t iCount = 0;
std::vector<CXFA_Node*> 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<CXFA_Node>(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, true);
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;
}
Optional<int32_t> CXFA_Node::GetNumberOfCells() {
CXFA_Node* pUIChild = GetUIChildNode();
if (!pUIChild)
return {};
if (CXFA_Comb* pNode =
pUIChild->GetChild<CXFA_Comb>(0, XFA_Element::Comb, false))
return {pNode->JSObject()->GetInteger(XFA_Attribute::NumberOfCells)};
return {};
}
bool CXFA_Node::IsMultiLine() {
CXFA_Node* pUIChild = GetUIChildNode();
return pUIChild && pUIChild->JSObject()->GetBoolean(XFA_Attribute::MultiLine);
}
std::pair<XFA_Element, int32_t> CXFA_Node::GetMaxChars() {
if (CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false)) {
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() {
CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
if (!pNode)
return -1;
CXFA_Decimal* pChild =
pNode->GetChild<CXFA_Decimal>(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() {
CXFA_Value* pNode = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
if (!pNode)
return -1;
CXFA_Decimal* pChild =
pNode->GetChild<CXFA_Decimal>(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();
LocaleIface* 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_Raw)
return WideString();
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
switch (ePicture) {
case XFA_VALUEPICTURE_Display: {
if (CXFA_Format* pFormat =
GetChild<CXFA_Format>(0, XFA_Element::Format, false)) {
if (CXFA_Picture* pPicture = pFormat->GetChild<CXFA_Picture>(
0, XFA_Element::Picture, false)) {
Optional<WideString> picture =
pPicture->JSObject()->TryContent(false, true);
if (picture)
return *picture;
}
}
LocaleIface* pLocale = GetLocale();
if (!pLocale)
return WideString();
uint32_t dwType = widgetValue.GetType();
switch (dwType) {
case XFA_VT_DATE:
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
case XFA_VT_TIME:
return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
case XFA_VT_DATETIME:
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium) +
L"T" +
pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium);
case XFA_VT_DECIMAL:
case XFA_VT_FLOAT:
default:
return WideString();
}
}
case XFA_VALUEPICTURE_Edit: {
CXFA_Ui* pUI = GetChild<CXFA_Ui>(0, XFA_Element::Ui, false);
if (pUI) {
if (CXFA_Picture* pPicture =
pUI->GetChild<CXFA_Picture>(0, XFA_Element::Picture, false)) {
Optional<WideString> picture =
pPicture->JSObject()->TryContent(false, true);
if (picture)
return *picture;
}
}
LocaleIface* pLocale = GetLocale();
if (!pLocale)
return WideString();
uint32_t dwType = widgetValue.GetType();
switch (dwType) {
case XFA_VT_DATE:
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
case XFA_VT_TIME:
return pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
case XFA_VT_DATETIME:
return pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short) +
L"T" +
pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short);
default:
return WideString();
}
}
case XFA_VALUEPICTURE_DataBind: {
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_Display)
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_Display) {
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_Raw && wsPicture.IsEmpty()) {
LocaleIface* pLocale = GetLocale();
if (eValueType == XFA_VALUEPICTURE_Display && pLocale)
wsValue = FormatNumStr(NormalizeNumStr(wsValue), pLocale);
}
break;
default:
break;
}
if (wsPicture.IsEmpty())
return wsValue;
if (LocaleIface* pLocale = GetLocale()) {
CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
switch (widgetValue.GetType()) {
case XFA_VT_DATE: {
WideString wsDate, wsTime;
if (SplitDateTime(wsValue, wsDate, wsTime)) {
CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocaleMgr);
if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType))
return wsValue;
}
break;
}
case XFA_VT_TIME: {
WideString wsDate, wsTime;
if (SplitDateTime(wsValue, wsDate, wsTime)) {
CXFA_LocaleValue time(XFA_VT_TIME, 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_DataBind);
if (wsPicture.IsEmpty())
return wsValue;
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
LocaleIface* 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_DataBind);
if (wsPicture.IsEmpty())
return wsValue;
WideString wsFormattedValue = wsValue;
if (LocaleIface* pLocale = GetLocale()) {
CXFA_Value* pNodeValue = GetChild<CXFA_Value>(0, XFA_Element::Value, false);
if (!pNodeValue)
return wsValue;
CXFA_Node* pValueChild = pNodeValue->GetFirstChild();
if (!pValueChild)
return wsValue;
int32_t iVTType = XFA_VT_NULL;
switch (pValueChild->GetElementType()) {
case XFA_Element::Decimal:
iVTType = XFA_VT_DECIMAL;
break;
case XFA_Element::Float:
iVTType = XFA_VT_FLOAT;
break;
case XFA_Element::Date:
iVTType = XFA_VT_DATE;
break;
case XFA_Element::Time:
iVTType = XFA_VT_TIME;
break;
case XFA_Element::DateTime:
iVTType = XFA_VT_DATETIME;
break;
case XFA_Element::Boolean:
iVTType = XFA_VT_BOOLEAN;
break;
case XFA_Element::Integer:
iVTType = XFA_VT_INTEGER;
break;
case XFA_Element::Text:
iVTType = XFA_VT_TEXT;
break;
default:
iVTType = XFA_VT_NULL;
break;
}
CXFA_LocaleMgr* pLocaleMgr = GetDocument()->GetLocaleMgr();
CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocaleMgr);
switch (widgetValue.GetType()) {
case XFA_VT_DATE: {
WideString wsDate, wsTime;
if (SplitDateTime(wsValue, wsDate, wsTime)) {
CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocaleMgr);
if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
XFA_VALUEPICTURE_DataBind)) {
return wsFormattedValue;
}
}
break;
}
case XFA_VT_TIME: {
WideString wsDate, wsTime;
if (SplitDateTime(wsValue, wsDate, wsTime)) {
CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocaleMgr);
if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
XFA_VALUEPICTURE_DataBind)) {
return wsFormattedValue;
}
}
break;
}
default:
break;
}
widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
XFA_VALUEPICTURE_DataBind);
}
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;
WideString wsRet;
int32_t iLead_ = 0, iTread_ = -1;
int32_t iCount = wsValue.GetLength();
if (iCount == 0)
return wsValue;
int32_t i = 0;
if (wsValue[i] == L'-') {
wsRet += L'-';
i++;
}
for (; i < iCount; i++) {
wchar_t wc = wsValue[i];
if (FXSYS_IsDecimalDigit(wc)) {
if (iLead >= 0) {
iLead_++;
if (iLead_ > iLead)
return L"0";
} else if (iTread_ >= 0) {
iTread_++;
if (iTread_ > iTread) {
if (iTread != -1) {
CFGAS_Decimal wsDeci = CFGAS_Decimal(wsValue.AsStringView());
wsDeci.SetScale(iTread);
wsRet = wsDeci.ToWideString();
}
return wsRet;
}
}
} else if (wc == L'.') {
iTread_ = 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_UnusedNode);
}
}
void CXFA_Node::SetToXML(const WideString& value) {
auto* pNode = GetXMLMappingNode();
switch (pNode->GetType()) {
case CFX_XMLNode::Type::kElement: {
auto* elem = static_cast<CFX_XMLElement*>(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<CFX_XMLText>(value);
elem->AppendLastChild(text);
break;
}
case CFX_XMLNode::Type::kText:
ToXMLText(GetXMLMappingNode())->SetText(value);
break;
default:
NOTREACHED();
}
}
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()->GetHDOC()->GetXMLDocument();
}
// static
std::unique_ptr<CXFA_Node> CXFA_Node::Create(CXFA_Document* doc,
XFA_Element element,
XFA_PacketType packet) {
std::unique_ptr<CXFA_Node> node;
switch (element) {
case XFA_Element::Ps:
node = pdfium::MakeUnique<CXFA_Ps>(doc, packet);
break;
case XFA_Element::To:
node = pdfium::MakeUnique<CXFA_To>(doc, packet);
break;
case XFA_Element::Ui:
node = pdfium::MakeUnique<CXFA_Ui>(doc, packet);
break;
case XFA_Element::RecordSet:
node = pdfium::MakeUnique<CXFA_RecordSet>(doc, packet);
break;
case XFA_Element::SubsetBelow:
node = pdfium::MakeUnique<CXFA_SubsetBelow>(doc, packet);
break;
case XFA_Element::SubformSet:
node = pdfium::MakeUnique<CXFA_SubformSet>(doc, packet);
break;
case XFA_Element::AdobeExtensionLevel:
node = pdfium::MakeUnique<CXFA_AdobeExtensionLevel>(doc, packet);
break;
case XFA_Element::Typeface:
node = pdfium::MakeUnique<CXFA_Typeface>(doc, packet);
break;
case XFA_Element::Break:
node = pdfium::MakeUnique<CXFA_Break>(doc, packet);
break;
case XFA_Element::FontInfo:
node = pdfium::MakeUnique<CXFA_FontInfo>(doc, packet);
break;
case XFA_Element::NumberPattern:
node = pdfium::MakeUnique<CXFA_NumberPattern>(doc, packet);
break;
case XFA_Element::DynamicRender:
node = pdfium::MakeUnique<CXFA_DynamicRender>(doc, packet);
break;
case XFA_Element::PrintScaling:
node = pdfium::MakeUnique<CXFA_PrintScaling>(doc, packet);
break;
case XFA_Element::CheckButton:
node = pdfium::MakeUnique<CXFA_CheckButton>(doc, packet);
break;
case XFA_Element::DatePatterns:
node = pdfium::MakeUnique<CXFA_DatePatterns>(doc, packet);
break;
case XFA_Element::SourceSet:
node = pdfium::MakeUnique<CXFA_SourceSet>(doc, packet);
break;
case XFA_Element::Amd:
node = pdfium::MakeUnique<CXFA_Amd>(doc, packet);
break;
case XFA_Element::Arc:
node = pdfium::MakeUnique<CXFA_Arc>(doc, packet);
break;
case XFA_Element::Day:
node = pdfium::MakeUnique<CXFA_Day>(doc, packet);
break;
case XFA_Element::Era:
node = pdfium::MakeUnique<CXFA_Era>(doc, packet);
break;
case XFA_Element::Jog:
node = pdfium::MakeUnique<CXFA_Jog>(doc, packet);
break;
case XFA_Element::Log:
node = pdfium::MakeUnique<CXFA_Log>(doc, packet);
break;
case XFA_Element::Map:
node = pdfium::MakeUnique<CXFA_Map>(doc, packet);
break;
case XFA_Element::Mdp:
node = pdfium::MakeUnique<CXFA_Mdp>(doc, packet);
break;
case XFA_Element::BreakBefore:
node = pdfium::MakeUnique<CXFA_BreakBefore>(doc, packet);
break;
case XFA_Element::Oid:
node = pdfium::MakeUnique<CXFA_Oid>(doc, packet);
break;
case XFA_Element::Pcl:
node = pdfium::MakeUnique<CXFA_Pcl>(doc, packet);
break;
case XFA_Element::Pdf:
node = pdfium::MakeUnique<CXFA_Pdf>(doc, packet);
break;
case XFA_Element::Ref:
node = pdfium::MakeUnique<CXFA_Ref>(doc, packet);
break;
case XFA_Element::Uri:
node = pdfium::MakeUnique<CXFA_Uri>(doc, packet);
break;
case XFA_Element::Xdc:
node = pdfium::MakeUnique<CXFA_Xdc>(doc, packet);
break;
case XFA_Element::Xdp:
node = pdfium::MakeUnique<CXFA_Xdp>(doc, packet);
break;
case XFA_Element::Xfa:
node = pdfium::MakeUnique<CXFA_Xfa>(doc, packet);
break;
case XFA_Element::Xsl:
node = pdfium::MakeUnique<CXFA_Xsl>(doc, packet);
break;
case XFA_Element::Zpl:
node = pdfium::MakeUnique<CXFA_Zpl>(doc, packet);
break;
case XFA_Element::Cache:
node = pdfium::MakeUnique<CXFA_Cache>(doc, packet);
break;
case XFA_Element::Margin:
node = pdfium::MakeUnique<CXFA_Margin>(doc, packet);
break;
case XFA_Element::KeyUsage:
node = pdfium::MakeUnique<CXFA_KeyUsage>(doc, packet);
break;
case XFA_Element::Exclude:
node = pdfium::MakeUnique<CXFA_Exclude>(doc, packet);
break;
case XFA_Element::ChoiceList:
node = pdfium::MakeUnique<CXFA_ChoiceList>(doc, packet);
break;
case XFA_Element::Level:
node = pdfium::MakeUnique<CXFA_Level>(doc, packet);
break;
case XFA_Element::LabelPrinter:
node = pdfium::MakeUnique<CXFA_LabelPrinter>(doc, packet);
break;
case XFA_Element::CalendarSymbols:
node = pdfium::MakeUnique<CXFA_CalendarSymbols>(doc, packet);
break;
case XFA_Element::Para:
node = pdfium::MakeUnique<CXFA_Para>(doc, packet);
break;
case XFA_Element::Part:
node = pdfium::MakeUnique<CXFA_Part>(doc, packet);
break;
case XFA_Element::Pdfa:
node = pdfium::MakeUnique<CXFA_Pdfa>(doc, packet);
break;
case XFA_Element::Filter:
node = pdfium::MakeUnique<CXFA_Filter>(doc, packet);
break;
case XFA_Element::Present:
node = pdfium::MakeUnique<CXFA_Present>(doc, packet);
break;
case XFA_Element::Pagination:
node = pdfium::MakeUnique<CXFA_Pagination>(doc, packet);
break;
case XFA_Element::Encoding:
node = pdfium::MakeUnique<CXFA_Encoding>(doc, packet);
break;
case XFA_Element::Event:
node = pdfium::MakeUnique<CXFA_Event>(doc, packet);
break;
case XFA_Element::Whitespace:
node = pdfium::MakeUnique<CXFA_Whitespace>(doc, packet);
break;
case XFA_Element::DefaultUi:
node = pdfium::MakeUnique<CXFA_DefaultUi>(doc, packet);
break;
case XFA_Element::DataModel:
node = pdfium::MakeUnique<CXFA_DataModel>(doc, packet);
break;
case XFA_Element::Barcode:
node = pdfium::MakeUnique<CXFA_Barcode>(doc, packet);
break;
case XFA_Element::TimePattern:
node = pdfium::MakeUnique<CXFA_TimePattern>(doc, packet);
break;
case XFA_Element::BatchOutput:
node = pdfium::MakeUnique<CXFA_BatchOutput>(doc, packet);
break;
case XFA_Element::Enforce:
node = pdfium::MakeUnique<CXFA_Enforce>(doc, packet);
break;
case XFA_Element::CurrencySymbols:
node = pdfium::MakeUnique<CXFA_CurrencySymbols>(doc, packet);
break;
case XFA_Element::AddSilentPrint:
node = pdfium::MakeUnique<CXFA_AddSilentPrint>(doc, packet);
break;
case XFA_Element::Rename:
node = pdfium::MakeUnique<CXFA_Rename>(doc, packet);
break;
case XFA_Element::Operation:
node = pdfium::MakeUnique<CXFA_Operation>(doc, packet);
break;
case XFA_Element::Typefaces:
node = pdfium::MakeUnique<CXFA_Typefaces>(doc, packet);
break;
case XFA_Element::SubjectDNs:
node = pdfium::MakeUnique<CXFA_SubjectDNs>(doc, packet);
break;
case XFA_Element::Issuers:
node = pdfium::MakeUnique<CXFA_Issuers>(doc, packet);
break;
case XFA_Element::WsdlConnection:
node = pdfium::MakeUnique<CXFA_WsdlConnection>(doc, packet);
break;
case XFA_Element::Debug:
node = pdfium::MakeUnique<CXFA_Debug>(doc, packet);
break;
case XFA_Element::Delta:
node = pdfium::MakeUnique<CXFA_Delta>(doc, packet);
break;
case XFA_Element::EraNames:
node = pdfium::MakeUnique<CXFA_EraNames>(doc, packet);
break;
case XFA_Element::ModifyAnnots:
node = pdfium::MakeUnique<CXFA_ModifyAnnots>(doc, packet);
break;
case XFA_Element::StartNode:
node = pdfium::MakeUnique<CXFA_StartNode>(doc, packet);
break;
case XFA_Element::Button:
node = pdfium::MakeUnique<CXFA_Button>(doc, packet);
break;
case XFA_Element::Format:
node = pdfium::MakeUnique<CXFA_Format>(doc, packet);
break;
case XFA_Element::Border:
node = pdfium::MakeUnique<CXFA_Border>(doc, packet);
break;
case XFA_Element::Area:
node = pdfium::MakeUnique<CXFA_Area>(doc, packet);
break;
case XFA_Element::Hyphenation:
node = pdfium::MakeUnique<CXFA_Hyphenation>(doc, packet);
break;
case XFA_Element::Text:
node = pdfium::MakeUnique<CXFA_Text>(doc, packet);
break;
case XFA_Element::Time:
node = pdfium::MakeUnique<CXFA_Time>(doc, packet);
break;
case XFA_Element::Type:
node = pdfium::MakeUnique<CXFA_Type>(doc, packet);
break;
case XFA_Element::Overprint:
node = pdfium::MakeUnique<CXFA_Overprint>(doc, packet);
break;
case XFA_Element::Certificates:
node = pdfium::MakeUnique<CXFA_Certificates>(doc, packet);
break;
case XFA_Element::EncryptionMethods:
node = pdfium::MakeUnique<CXFA_EncryptionMethods>(doc, packet);
break;
case XFA_Element::SetProperty:
node = pdfium::MakeUnique<CXFA_SetProperty>(doc, packet);
break;
case XFA_Element::PrinterName:
node = pdfium::MakeUnique<CXFA_PrinterName>(doc, packet);
break;
case XFA_Element::StartPage:
node = pdfium::MakeUnique<CXFA_StartPage>(doc, packet);
break;
case XFA_Element::PageOffset:
node = pdfium::MakeUnique<CXFA_PageOffset>(doc, packet);
break;
case XFA_Element::DateTime:
node = pdfium::MakeUnique<CXFA_DateTime>(doc, packet);
break;
case XFA_Element::Comb:
node = pdfium::MakeUnique<CXFA_Comb>(doc, packet);
break;
case XFA_Element::Pattern:
node = pdfium::MakeUnique<CXFA_Pattern>(doc, packet);
break;
case XFA_Element::IfEmpty:
node = pdfium::MakeUnique<CXFA_IfEmpty>(doc, packet);
break;
case XFA_Element::SuppressBanner:
node = pdfium::MakeUnique<CXFA_SuppressBanner>(doc, packet);
break;
case XFA_Element::OutputBin:
node = pdfium::MakeUnique<CXFA_OutputBin>(doc, packet);
break;
case XFA_Element::Field:
node = pdfium::MakeUnique<CXFA_Field>(doc, packet);
break;
case XFA_Element::Agent:
node = pdfium::MakeUnique<CXFA_Agent>(doc, packet);
break;
case XFA_Element::OutputXSL:
node = pdfium::MakeUnique<CXFA_OutputXSL>(doc, packet);
break;
case XFA_Element::AdjustData:
node = pdfium::MakeUnique<CXFA_AdjustData>(doc, packet);
break;
case XFA_Element::AutoSave:
node = pdfium::MakeUnique<CXFA_AutoSave>(doc, packet);
break;
case XFA_Element::ContentArea:
node = pdfium::MakeUnique<CXFA_ContentArea>(doc, packet);
break;
case XFA_Element::WsdlAddress:
node = pdfium::MakeUnique<CXFA_WsdlAddress>(doc, packet);
break;
case XFA_Element::Solid:
node = pdfium::MakeUnique<CXFA_Solid>(doc, packet);
break;
case XFA_Element::DateTimeSymbols:
node = pdfium::MakeUnique<CXFA_DateTimeSymbols>(doc, packet);
break;
case XFA_Element::EncryptionLevel:
node = pdfium::MakeUnique<CXFA_EncryptionLevel>(doc, packet);
break;
case XFA_Element::Edge:
node = pdfium::MakeUnique<CXFA_Edge>(doc, packet);
break;
case XFA_Element::Stipple:
node = pdfium::MakeUnique<CXFA_Stipple>(doc, packet);
break;
case XFA_Element::Attributes:
node = pdfium::MakeUnique<CXFA_Attributes>(doc, packet);
break;
case XFA_Element::VersionControl:
node = pdfium::MakeUnique<CXFA_VersionControl>(doc, packet);
break;
case XFA_Element::Meridiem:
node = pdfium::MakeUnique<CXFA_Meridiem>(doc, packet);
break;
case XFA_Element::ExclGroup:
node = pdfium::MakeUnique<CXFA_ExclGroup>(doc, packet);
break;
case XFA_Element::ToolTip:
node = pdfium::MakeUnique<CXFA_ToolTip>(doc, packet);
break;
case XFA_Element::Compress:
node = pdfium::MakeUnique<CXFA_Compress>(doc, packet);
break;
case XFA_Element::Reason:
node = pdfium::MakeUnique<CXFA_Reason>(doc, packet);
break;
case XFA_Element::Execute:
node = pdfium::MakeUnique<CXFA_Execute>(doc, packet);
break;
case XFA_Element::ContentCopy:
node = pdfium::MakeUnique<CXFA_ContentCopy>(doc, packet);
break;
case XFA_Element::DateTimeEdit:
node = pdfium::MakeUnique<CXFA_DateTimeEdit>(doc, packet);
break;
case XFA_Element::Config:
node = pdfium::MakeUnique<CXFA_Config>(doc, packet);
break;
case XFA_Element::Image:
node = pdfium::MakeUnique<CXFA_Image>(doc, packet);
break;
case XFA_Element::SharpxHTML:
node = pdfium::MakeUnique<CXFA_SharpxHTML>(doc, packet);
break;
case XFA_Element::NumberOfCopies:
node = pdfium::MakeUnique<CXFA_NumberOfCopies>(doc, packet);
break;
case XFA_Element::BehaviorOverride:
node = pdfium::MakeUnique<CXFA_BehaviorOverride>(doc, packet);
break;
case XFA_Element::TimeStamp:
node = pdfium::MakeUnique<CXFA_TimeStamp>(doc, packet);
break;
case XFA_Element::Month:
node = pdfium::MakeUnique<CXFA_Month>(doc, packet);
break;
case XFA_Element::ViewerPreferences:
node = pdfium::MakeUnique<CXFA_ViewerPreferences>(doc, packet);
break;
case XFA_Element::ScriptModel:
node = pdfium::MakeUnique<CXFA_ScriptModel>(doc, packet);
break;
case XFA_Element::Decimal:
node = pdfium::MakeUnique<CXFA_Decimal>(doc, packet);
break;
case XFA_Element::Subform:
node = pdfium::MakeUnique<CXFA_Subform>(doc, packet);
break;
case XFA_Element::Select:
node = pdfium::MakeUnique<CXFA_Select>(doc, packet);
break;
case XFA_Element::Window:
node = pdfium::MakeUnique<CXFA_Window>(doc, packet);
break;
case XFA_Element::LocaleSet:
node = pdfium::MakeUnique<CXFA_LocaleSet>(doc, packet);
break;
case XFA_Element::Handler:
node = pdfium::MakeUnique<CXFA_Handler>(doc, packet);
break;
case XFA_Element::Presence:
node = pdfium::MakeUnique<CXFA_Presence>(doc, packet);
break;
case XFA_Element::Record:
node = pdfium::MakeUnique<CXFA_Record>(doc, packet);
break;
case XFA_Element::Embed:
node = pdfium::MakeUnique<CXFA_Embed>(doc, packet);
break;
case XFA_Element::Version:
node = pdfium::MakeUnique<CXFA_Version>(doc, packet);
break;
case XFA_Element::Command:
node = pdfium::MakeUnique<CXFA_Command>(doc, packet);
break;
case XFA_Element::Copies:
node = pdfium::MakeUnique<CXFA_Copies>(doc, packet);
break;
case XFA_Element::Staple:
node = pdfium::MakeUnique<CXFA_Staple>(doc, packet);
break;
case XFA_Element::SubmitFormat:
node = pdfium::MakeUnique<CXFA_SubmitFormat>(doc, packet);
break;
case XFA_Element::Boolean:
node = pdfium::MakeUnique<CXFA_Boolean>(doc, packet);
break;
case XFA_Element::Message:
node = pdfium::MakeUnique<CXFA_Message>(doc, packet);
break;
case XFA_Element::Output:
node = pdfium::MakeUnique<CXFA_Output>(doc, packet);
break;
case XFA_Element::PsMap:
node = pdfium::MakeUnique<CXFA_PsMap>(doc, packet);
break;
case XFA_Element::ExcludeNS:
node = pdfium::MakeUnique<CXFA_ExcludeNS>(doc, packet);
break;
case XFA_Element::Assist:
node = pdfium::MakeUnique<CXFA_Assist>(doc, packet);
break;
case XFA_Element::Picture:
node = pdfium::MakeUnique<CXFA_Picture>(doc, packet);
break;
case XFA_Element::Traversal:
node = pdfium::MakeUnique<CXFA_Traversal>(doc, packet);
break;
case XFA_Element::SilentPrint:
node = pdfium::MakeUnique<CXFA_SilentPrint>(doc, packet);
break;
case XFA_Element::WebClient:
node = pdfium::MakeUnique<CXFA_WebClient>(doc, packet);
break;
case XFA_Element::Producer:
node = pdfium::MakeUnique<CXFA_Producer>(doc, packet);
break;
case XFA_Element::Corner:
node = pdfium::MakeUnique<CXFA_Corner>(doc, packet);
break;
case XFA_Element::MsgId:
node = pdfium::MakeUnique<CXFA_MsgId>(doc, packet);
break;
case XFA_Element::Color:
node = pdfium::MakeUnique<CXFA_Color>(doc, packet);
break;
case XFA_Element::Keep:
node = pdfium::MakeUnique<CXFA_Keep>(doc, packet);
break;
case XFA_Element::Query:
node = pdfium::MakeUnique<CXFA_Query>(doc, packet);
break;
case XFA_Element::Insert:
node = pdfium::MakeUnique<CXFA_Insert>(doc, packet);
break;
case XFA_Element::ImageEdit:
node = pdfium::MakeUnique<CXFA_ImageEdit>(doc, packet);
break;
case XFA_Element::Validate:
node = pdfium::MakeUnique<CXFA_Validate>(doc, packet);
break;
case XFA_Element::DigestMethods:
node = pdfium::MakeUnique<CXFA_DigestMethods>(doc, packet);
break;
case XFA_Element::NumberPatterns:
node = pdfium::MakeUnique<CXFA_NumberPatterns>(doc, packet);
break;
case XFA_Element::PageSet:
node = pdfium::MakeUnique<CXFA_PageSet>(doc, packet);
break;
case XFA_Element::Integer:
node = pdfium::MakeUnique<CXFA_Integer>(doc, packet);
break;
case XFA_Element::SoapAddress:
node = pdfium::MakeUnique<CXFA_SoapAddress>(doc, packet);
break;
case XFA_Element::Equate:
node = pdfium::MakeUnique<CXFA_Equate>(doc, packet);
break;
case XFA_Element::FormFieldFilling:
node = pdfium::MakeUnique<CXFA_FormFieldFilling>(doc, packet);
break;
case XFA_Element::PageRange:
node = pdfium::MakeUnique<CXFA_PageRange>(doc, packet);
break;
case XFA_Element::Update:
node = pdfium::MakeUnique<CXFA_Update>(doc, packet);
break;
case XFA_Element::ConnectString:
node = pdfium::MakeUnique<CXFA_ConnectString>(doc, packet);
break;
case XFA_Element::Mode:
node = pdfium::MakeUnique<CXFA_Mode>(doc, packet);
break;
case XFA_Element::Layout:
node = pdfium::MakeUnique<CXFA_Layout>(doc, packet);
break;
case XFA_Element::Sharpxml:
node = pdfium::MakeUnique<CXFA_Sharpxml>(doc, packet);
break;
case XFA_Element::XsdConnection:
node = pdfium::MakeUnique<CXFA_XsdConnection>(doc, packet);
break;
case XFA_Element::Traverse:
node = pdfium::MakeUnique<CXFA_Traverse>(doc, packet);
break;
case XFA_Element::Encodings:
node = pdfium::MakeUnique<CXFA_Encodings>(doc, packet);
break;
case XFA_Element::Template:
node = pdfium::MakeUnique<CXFA_Template>(doc, packet);
break;
case XFA_Element::Acrobat:
node = pdfium::MakeUnique<CXFA_Acrobat>(doc, packet);
break;
case XFA_Element::ValidationMessaging:
node = pdfium::MakeUnique<CXFA_ValidationMessaging>(doc, packet);
break;
case XFA_Element::Signing:
node = pdfium::MakeUnique<CXFA_Signing>(doc, packet);
break;
case XFA_Element::Script:
node = pdfium::MakeUnique<CXFA_Script>(doc, packet);
break;
case XFA_Element::AddViewerPreferences:
node = pdfium::MakeUnique<CXFA_AddViewerPreferences>(doc, packet);
break;
case XFA_Element::AlwaysEmbed:
node = pdfium::MakeUnique<CXFA_AlwaysEmbed>(doc, packet);
break;
case XFA_Element::PasswordEdit:
node = pdfium::MakeUnique<CXFA_PasswordEdit>(doc, packet);
break;
case XFA_Element::NumericEdit:
node = pdfium::MakeUnique<CXFA_NumericEdit>(doc, packet);
break;
case XFA_Element::EncryptionMethod:
node = pdfium::MakeUnique<CXFA_EncryptionMethod>(doc, packet);
break;
case XFA_Element::Change:
node = pdfium::MakeUnique<CXFA_Change>(doc, packet);
break;
case XFA_Element::PageArea:
node = pdfium::MakeUnique<CXFA_PageArea>(doc, packet);
break;
case XFA_Element::SubmitUrl:
node = pdfium::MakeUnique<CXFA_SubmitUrl>(doc, packet);
break;
case XFA_Element::Oids:
node = pdfium::MakeUnique<CXFA_Oids>(doc, packet);
break;
case XFA_Element::Signature:
node = pdfium::MakeUnique<CXFA_Signature>(doc, packet);
break;
case XFA_Element::ADBE_JSConsole:
node = pdfium::MakeUnique<CXFA_ADBE_JSConsole>(doc, packet);
break;
case XFA_Element::Caption:
node = pdfium::MakeUnique<CXFA_Caption>(doc, packet);
break;
case XFA_Element::Relevant:
node = pdfium::MakeUnique<CXFA_Relevant>(doc, packet);
break;
case XFA_Element::FlipLabel:
node = pdfium::MakeUnique<CXFA_FlipLabel>(doc, packet);
break;
case XFA_Element::ExData:
node = pdfium::MakeUnique<CXFA_ExData>(doc, packet);
break;
case XFA_Element::DayNames:
node = pdfium::MakeUnique<CXFA_DayNames>(doc, packet);
break;
case XFA_Element::SoapAction:
node = pdfium::MakeUnique<CXFA_SoapAction>(doc, packet);
break;
case XFA_Element::DefaultTypeface:
node = pdfium::MakeUnique<CXFA_DefaultTypeface>(doc, packet);
break;
case XFA_Element::Manifest:
node = pdfium::MakeUnique<CXFA_Manifest>(doc, packet);
break;
case XFA_Element::Overflow:
node = pdfium::MakeUnique<CXFA_Overflow>(doc, packet);
break;
case XFA_Element::Linear:
node = pdfium::MakeUnique<CXFA_Linear>(doc, packet);
break;
case XFA_Element::CurrencySymbol:
node = pdfium::MakeUnique<CXFA_CurrencySymbol>(doc, packet);
break;
case XFA_Element::Delete:
node = pdfium::MakeUnique<CXFA_Delete>(doc, packet);
break;
case XFA_Element::DigestMethod:
node = pdfium::MakeUnique<CXFA_DigestMethod>(doc, packet);
break;
case XFA_Element::InstanceManager:
node = pdfium::MakeUnique<CXFA_InstanceManager>(doc, packet);
break;
case XFA_Element::EquateRange:
node = pdfium::MakeUnique<CXFA_EquateRange>(doc, packet);
break;
case XFA_Element::Medium:
node = pdfium::MakeUnique<CXFA_Medium>(doc, packet);
break;
case XFA_Element::TextEdit:
node = pdfium::MakeUnique<CXFA_TextEdit>(doc, packet);
break;
case XFA_Element::TemplateCache:
node = pdfium::MakeUnique<CXFA_TemplateCache>(doc, packet);
break;
case XFA_Element::CompressObjectStream:
node = pdfium::MakeUnique<CXFA_CompressObjectStream>(doc, packet);
break;
case XFA_Element::DataValue:
node = pdfium::MakeUnique<CXFA_DataValue>(doc, packet);
break;
case XFA_Element::AccessibleContent:
node = pdfium::MakeUnique<CXFA_AccessibleContent>(doc, packet);
break;
case XFA_Element::IncludeXDPContent:
node = pdfium::MakeUnique<CXFA_IncludeXDPContent>(doc, packet);
break;
case XFA_Element::XmlConnection:
node = pdfium::MakeUnique<CXFA_XmlConnection>(doc, packet);
break;
case XFA_Element::ValidateApprovalSignatures:
node = pdfium::MakeUnique<CXFA_ValidateApprovalSignatures>(doc, packet);
break;
case XFA_Element::SignData:
node = pdfium::MakeUnique<CXFA_SignData>(doc, packet);
break;
case XFA_Element::Packets:
node = pdfium::MakeUnique<CXFA_Packets>(doc, packet);
break;
case XFA_Element::DatePattern:
node = pdfium::MakeUnique<CXFA_DatePattern>(doc, packet);
break;
case XFA_Element::DuplexOption:
node = pdfium::MakeUnique<CXFA_DuplexOption>(doc, packet);
break;
case XFA_Element::Base:
node = pdfium::MakeUnique<CXFA_Base>(doc, packet);
break;
case XFA_Element::Bind:
node = pdfium::MakeUnique<CXFA_Bind>(doc, packet);
break;
case XFA_Element::Compression:
node = pdfium::MakeUnique<CXFA_Compression>(doc, packet);
break;
case XFA_Element::User:
node = pdfium::MakeUnique<CXFA_User>(doc, packet);
break;
case XFA_Element::Rectangle:
node = pdfium::MakeUnique<CXFA_Rectangle>(doc, packet);
break;
case XFA_Element::EffectiveOutputPolicy:
node = pdfium::MakeUnique<CXFA_EffectiveOutputPolicy>(doc, packet);
break;
case XFA_Element::ADBE_JSDebugger:
node = pdfium::MakeUnique<CXFA_ADBE_JSDebugger>(doc, packet);
break;
case XFA_Element::Acrobat7:
node = pdfium::MakeUnique<CXFA_Acrobat7>(doc, packet);
break;
case XFA_Element::Interactive:
node = pdfium::MakeUnique<CXFA_Interactive>(doc, packet);
break;
case XFA_Element::Locale:
node = pdfium::MakeUnique<CXFA_Locale>(doc, packet);
break;
case XFA_Element::CurrentPage:
node = pdfium::MakeUnique<CXFA_CurrentPage>(doc, packet);
break;
case XFA_Element::Data:
node = pdfium::MakeUnique<CXFA_Data>(doc, packet);
break;
case XFA_Element::Date:
node = pdfium::MakeUnique<CXFA_Date>(doc, packet);
break;
case XFA_Element::Desc:
node = pdfium::MakeUnique<CXFA_Desc>(doc, packet);
break;
case XFA_Element::Encrypt:
node = pdfium::MakeUnique<CXFA_Encrypt>(doc, packet);
break;
case XFA_Element::Draw:
node = pdfium::MakeUnique<CXFA_Draw>(doc, packet);
break;
case XFA_Element::Encryption:
node = pdfium::MakeUnique<CXFA_Encryption>(doc, packet);
break;
case XFA_Element::MeridiemNames:
node = pdfium::MakeUnique<CXFA_MeridiemNames>(doc, packet);
break;
case XFA_Element::Messaging:
node = pdfium::MakeUnique<CXFA_Messaging>(doc, packet);
break;
case XFA_Element::Speak:
node = pdfium::MakeUnique<CXFA_Speak>(doc, packet);
break;
case XFA_Element::DataGroup:
node = pdfium::MakeUnique<CXFA_DataGroup>(doc, packet);
break;
case XFA_Element::Common:
node = pdfium::MakeUnique<CXFA_Common>(doc, packet);
break;
case XFA_Element::Sharptext:
node = pdfium::MakeUnique<CXFA_Sharptext>(doc, packet);
break;
case XFA_Element::PaginationOverride:
node = pdfium::MakeUnique<CXFA_PaginationOverride>(doc, packet);
break;
case XFA_Element::Reasons:
node = pdfium::MakeUnique<CXFA_Reasons>(doc, packet);
break;
case XFA_Element::SignatureProperties:
node = pdfium::MakeUnique<CXFA_SignatureProperties>(doc, packet);
break;
case XFA_Element::Threshold:
node = pdfium::MakeUnique<CXFA_Threshold>(doc, packet);
break;
case XFA_Element::AppearanceFilter:
node = pdfium::MakeUnique<CXFA_AppearanceFilter>(doc, packet);
break;
case XFA_Element::Fill:
node = pdfium::MakeUnique<CXFA_Fill>(doc, packet);
break;
case XFA_Element::Font:
node = pdfium::MakeUnique<CXFA_Font>(doc, packet);
break;
case XFA_Element::Form:
node = pdfium::MakeUnique<CXFA_Form>(doc, packet);
break;
case XFA_Element::MediumInfo:
node = pdfium::MakeUnique<CXFA_MediumInfo>(doc, packet);
break;
case XFA_Element::Certificate:
node = pdfium::MakeUnique<CXFA_Certificate>(doc, packet);
break;
case XFA_Element::Password:
node = pdfium::MakeUnique<CXFA_Password>(doc, packet);
break;
case XFA_Element::RunScripts:
node = pdfium::MakeUnique<CXFA_RunScripts>(doc, packet);
break;
case XFA_Element::Trace:
node = pdfium::MakeUnique<CXFA_Trace>(doc, packet);
break;
case XFA_Element::Float:
node = pdfium::MakeUnique<CXFA_Float>(doc, packet);
break;
case XFA_Element::RenderPolicy:
node = pdfium::MakeUnique<CXFA_RenderPolicy>(doc, packet);
break;
case XFA_Element::Destination:
node = pdfium::MakeUnique<CXFA_Destination>(doc, packet);
break;
case XFA_Element::Value:
node = pdfium::MakeUnique<CXFA_Value>(doc, packet);
break;
case XFA_Element::Bookend:
node = pdfium::MakeUnique<CXFA_Bookend>(doc, packet);
break;
case XFA_Element::ExObject:
node = pdfium::MakeUnique<CXFA_ExObject>(doc, packet);
break;
case XFA_Element::OpenAction:
node = pdfium::MakeUnique<CXFA_OpenAction>(doc, packet);
break;
case XFA_Element::NeverEmbed:
node = pdfium::MakeUnique<CXFA_NeverEmbed>(doc, packet);
break;
case XFA_Element::BindItems:
node = pdfium::MakeUnique<CXFA_BindItems>(doc, packet);
break;
case XFA_Element::Calculate:
node = pdfium::MakeUnique<CXFA_Calculate>(doc, packet);
break;
case XFA_Element::Print:
node = pdfium::MakeUnique<CXFA_Print>(doc, packet);
break;
case XFA_Element::Extras:
node = pdfium::MakeUnique<CXFA_Extras>(doc, packet);
break;
case XFA_Element::Proto:
node = pdfium::MakeUnique<CXFA_Proto>(doc, packet);
break;
case XFA_Element::DSigData:
node = pdfium::MakeUnique<CXFA_DSigData>(doc, packet);
break;
case XFA_Element::Creator:
node = pdfium::MakeUnique<CXFA_Creator>(doc, packet);
break;
case XFA_Element::Connect:
node = pdfium::MakeUnique<CXFA_Connect>(doc, packet);
break;
case XFA_Element::Permissions:
node = pdfium::MakeUnique<CXFA_Permissions>(doc, packet);
break;
case XFA_Element::ConnectionSet:
node = pdfium::MakeUnique<CXFA_ConnectionSet>(doc, packet);
break;
case XFA_Element::Submit:
node = pdfium::MakeUnique<CXFA_Submit>(doc, packet);
break;
case XFA_Element::Range:
node = pdfium::MakeUnique<CXFA_Range>(doc, packet);
break;
case XFA_Element::Linearized:
node = pdfium::MakeUnique<CXFA_Linearized>(doc, packet);
break;
case XFA_Element::Packet:
node = pdfium::MakeUnique<CXFA_Packet>(doc, packet);
break;
case XFA_Element::RootElement:
node = pdfium::MakeUnique<CXFA_RootElement>(doc, packet);
break;
case XFA_Element::PlaintextMetadata:
node = pdfium::MakeUnique<CXFA_PlaintextMetadata>(doc, packet);
break;
case XFA_Element::NumberSymbols:
node = pdfium::MakeUnique<CXFA_NumberSymbols>(doc, packet);
break;
case XFA_Element::PrintHighQuality:
node = pdfium::MakeUnique<CXFA_PrintHighQuality>(doc, packet);
break;
case XFA_Element::Driver:
node = pdfium::MakeUnique<CXFA_Driver>(doc, packet);
break;
case XFA_Element::IncrementalLoad:
node = pdfium::MakeUnique<CXFA_IncrementalLoad>(doc, packet);
break;
case XFA_Element::SubjectDN:
node = pdfium::MakeUnique<CXFA_SubjectDN>(doc, packet);
break;
case XFA_Element::CompressLogicalStructure:
node = pdfium::MakeUnique<CXFA_CompressLogicalStructure>(doc, packet);
break;
case XFA_Element::IncrementalMerge:
node = pdfium::MakeUnique<CXFA_IncrementalMerge>(doc, packet);
break;
case XFA_Element::Radial:
node = pdfium::MakeUnique<CXFA_Radial>(doc, packet);
break;
case XFA_Element::Variables:
node = pdfium::MakeUnique<CXFA_Variables>(doc, packet);
break;
case XFA_Element::TimePatterns:
node = pdfium::MakeUnique<CXFA_TimePatterns>(doc, packet);
break;
case XFA_Element::EffectiveInputPolicy:
node = pdfium::MakeUnique<CXFA_EffectiveInputPolicy>(doc, packet);
break;
case XFA_Element::NameAttr:
node = pdfium::MakeUnique<CXFA_NameAttr>(doc, packet);
break;
case XFA_Element::Conformance:
node = pdfium::MakeUnique<CXFA_Conformance>(doc, packet);
break;
case XFA_Element::Transform:
node = pdfium::MakeUnique<CXFA_Transform>(doc, packet);
break;
case XFA_Element::LockDocument:
node = pdfium::MakeUnique<CXFA_LockDocument>(doc, packet);
break;
case XFA_Element::BreakAfter:
node = pdfium::MakeUnique<CXFA_BreakAfter>(doc, packet);
break;
case XFA_Element::Line:
node = pdfium::MakeUnique<CXFA_Line>(doc, packet);
break;
case XFA_Element::Source:
node = pdfium::MakeUnique<CXFA_Source>(doc, packet);
break;
case XFA_Element::Occur:
node = pdfium::MakeUnique<CXFA_Occur>(doc, packet);
break;
case XFA_Element::PickTrayByPDFSize:
node = pdfium::MakeUnique<CXFA_PickTrayByPDFSize>(doc, packet);
break;
case XFA_Element::MonthNames:
node = pdfium::MakeUnique<CXFA_MonthNames>(doc, packet);
break;
case XFA_Element::Severity:
node = pdfium::MakeUnique<CXFA_Severity>(doc, packet);
break;
case XFA_Element::GroupParent:
node = pdfium::MakeUnique<CXFA_GroupParent>(doc, packet);
break;
case XFA_Element::DocumentAssembly:
node = pdfium::MakeUnique<CXFA_DocumentAssembly>(doc, packet);
break;
case XFA_Element::NumberSymbol:
node = pdfium::MakeUnique<CXFA_NumberSymbol>(doc, packet);
break;
case XFA_Element::Tagged:
node = pdfium::MakeUnique<CXFA_Tagged>(doc, packet);
break;
case XFA_Element::Items:
node = pdfium::MakeUnique<CXFA_Items>(doc, packet);
break;
default:
NOTREACHED();
return nullptr;
}
if (!node || !node->IsValidInPacket(packet))
return nullptr;
return node;
}