% \iffalse meta-comment
%
% Copyright (C) 2011-2023 by Scott Pakin <scott+hyxmp@pakin.org>
% --------------------------------------------------------------
%
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in:
%
%    http://www.latex-project.org/lppl.txt
%
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008/05/04 or later.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{hyperxmp.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{hyperxmp}
%<*package>
    [2022/10/16 v5.11 Store hyperref metadata in XMP format]
%</package>
%
%<*driver>
\bgroup
  \catcode`\&=11
  \gdef\levelchar{&}
\egroup
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{graphicx}
\usepackage[cmyk]{xcolor}
\usepackage{tocbibind}
\usepackage{microtype}
\usepackage{needspace}
\usepackage{varioref}
\usepackage{fancyvrb}
\usepackage{multicol}
\usepackage{makeidx}
\usepackage{mmap}
\usepackage{enumitem}
\usepackage{listings}
\usepackage[labelformat=simple]{subcaption}
\renewcommand\thesubfigure{(\alph{subfigure})}
\usepackage{array}
\usepackage{booktabs}
\usepackage{marginfix}
\usepackage{ifmtarg}
\usepackage{iftex}
\input{hyperxmp-stds}
\expandafter\ifx\csname wantpdfstandards\endcsname\relax
  \usepackage{hyperref}
\else
  \usepackage[pdfa]{hyperref}
\fi
\usepackage{hyperxmp}
\EnableCrossrefs
\CodelineIndex
\RecordChanges

% Specify this document's metadata.
\GetFileInfo{hyperxmp.dtx}
\title{The \pkgname{hyperxmp} package\thanks{This document
  corresponds to \pkgname{hyperxmp}~\fileversion, dated \filedate.}}
\author{Scott Pakin \\ \texttt{scott+hyxmp@pakin.org}}
\makeatletter
\edef\versionnumber{\expandafter\@gobble\fileversion}  % Drop the "v" in the file version.
\makeatother
\hypersetup{%
  pdfauthor={Scott Pakin},
  pdftitle={The hyperxmp package},
  pdfsubject={LaTeX2e support for XMP metadata},
  pdfkeywords={LaTeX, embedded metadata, XMP, PDF, copyright, license, comments},
  pdfcopyright={Copyright (C) 2011-2023, Scott Pakin},
  pdflicenseurl={http://www.latex-project.org/lppl/},
  pdfcaptionwriter={Scott Pakin},
  pdfcontactemail={scott+hyxmp@pakin.org},
  pdfcontacturl={http://www.pakin.org/\xmptilde scott/},
  pdfversionid={\versionnumber},
  pdflang={en-US},
  pdftrapped={False},
  pdfstartpage={},
  pdfsource={hyperxmp.dtx},
  pdfurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/hyperxmp.pdf},
  baseurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/}
}

% Specify some additional hyperref configuration.
\hypersetup{%
  unicode,
  bookmarksopen,
  bookmarksopenlevel=2,
  bookmarksnumbered
}

% Redefine \changes to properly sort v5.10 *after* v5.9.
\makeatletter
\let\orig@changes=\changes
\def\discard@suffix#1\relax{}
\def\pad@minor@ver v#1.#2\relax{%
  \afterassignment\discard@suffix
  \@tempcnta=#2\relax
  \edef\new@change@ver{%
    v#1.%
    \ifnum\@tempcnta<10
      0#2
    \else
      #2
    \fi
  }%
}
\renewcommand{\changes}[2]{%
  \pad@minor@ver#1\relax
  \orig@changes{\new@change@ver=#1}{#2}%
}
\makeatother

\begin{document}
  \DocInput{hyperxmp.dtx}
  \Needspace{10\baselineskip}
  \renewcommand*{\glossaryname}{Change History}
  \PrintChanges
  \Needspace{12\baselineskip}
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{2844}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v1.0}{2006/05/14}{Initial version}
% \changes{v2.0}{2012/08/02}{Heiko Oberdiek's major rewrite of the code
%   to better support native-Unicode \string\TeX\ implementations
%   (\string\XeTeX\ and \string\LuaTeX)}
% \changes{v2.0}{2012/08/26}{Added support for the \protect\acro{XMP} Basic
%   schema and miscellaneous other bits of metadata}
% \changes{v1.2}{2010/06/04}{Added support for the \protect\XeTeX\ backend
%   (\texttt{xdvipdfmx})}
% \changes{v1.2}{2010/06/07}{Added support for the Photoshop schema}
% \changes{v2.2}{2010/12/06}{Added support for the \protect\acro{IPTC} Photo Metadata schema}
% \changes{v2.4}{2013/12/21}{Added support for the \protect\acro{PDF/A}
%   Identification schema, as requested by Florian Breitwieser}
% \changes{v2.5}{2014/06/19}{Enabled ``\texttt{\string\string\string\_}''
%   to work within email addresses, as requested by Leonid Sinev}
% \changes{v2.6}{2014/09/24}{Added support for a new \protect\optname{pdfdate}
%   key to explicitly specify the document date (and optionally time)}
% \changes{v2.9}{2016/04/25}{Force inclusion of \protect\xmpprop{dc:creator},
%   \protect\xmpprop{dc:title}, and \protect\xmpprop{dc:description}---even if
%   empty---when \protect\pkgname{hyperref} is loaded with the
%   \protect\optname{pdfa} option (suggested by Leonid Sinev)}
% \changes{v2.9}{2016/04/26}{Introduced the \protect\optname{pdftype}
%   package option, which enables an author to specify the type of
%   document being produced}
% \changes{v3.0}{2016/07/02}{Made the code compatible with \string\LuaTeX~0.85.
%   Thanks to Robert Schlicht, Leonid Sinev, and David Carlisle for bug
%   reports and to Leonid Sinev for helping test the new
%   \protect\pkgname{hyperxmp} code}
% \changes{v3.4}{2017/11/04}{Use \protect\pkgname{ifmtarg} to test for
%   empty arguments, including non-empty but all spaces}
% \changes{v4.0}{2019/03/14}{Include all metadata within a single
%   \protect\xmpterm{rdf:Description} block}
% \changes{v4.1}{2019/04/05}{Updated the documentation to refer to
%   \protect\cs{pdfnumpages} by its correct name.  Thanks to Volker RW Schaa
%   for catching the discrepancy}
% \changes{v5.0}{2020/02/15}{Added support for \protect\acro{PDF/UA}
%   standards, as requested by Robin Schwab}
% \changes{v5.0}{2020/02/26}{Added support for \protect\acro{PDF/X}
%   standards, as requested by Robin Schwab}
% \changes{v5.0}{2020/03/17}{Don't set any document dates (creation,
%   modification, or metadata) from \string\optname{pdfdate}}
% \changes{v5.2}{2020/04/29}{Introduced the \protect\optname{pdfidentifier}
%   package option, which enables an author to specify a unique identifier
%   for the document}
% \changes{v5.5}{2020/07/23}{Introduced the \protect\optname{pdfpubstatus}
%   package option, which enables an author to specify the document's
%   publication status.  Thanks to Robin Schwab for pointing me to the
%   Journal Article Versions recommendation~\protect\cite{NISO2008:jav}}
% \changes{v5.5}{2020/07/25}{Automatically assign
%   \protect\optname{pdfnumpages} and \protect\optname{pdfbytes} under
%   \protect\pdfLaTeX\ and \protect\LuaLaTeX}
% \changes{v5.5}{2020/09/23}{Defer \protect\cs{AtEndPreamble} execution
%   until the end of the document.  This enables
%   \protect\pkgname{hyperxmp} itself to be loaded from
%   \protect\cs{AtEndPreamble}, as is done by
%   \protect\pkgname{doclicense}~v2.2.0.  Thanks to Tommaso Pecorella
%   for the bug report and help testing}
% \changes{v5.6}{2020/10/05}{Make conditional the loading of the
%   \protect\pkgname{ifdraft} package.  Thanks to Tobias Pape for
%   reporting the incompatibility between \protect\pkgname{hyperxmp} and
%   \protect\pkgname{ifdraft}}
%
% ^^A \GetFileInfo{hyperxmp.dtx}
%
% \DoNotIndex{\,,\&,\ ,\!,\",\#,\(,\),\*,\<,\>,\\,\^,\~,\^,\_}
% \DoNotIndex{\@cons,\@empty,\@firstofone,\@firstoftwo,\@gobble,\@gobbletwo}
% \DoNotIndex{\@ifpackageloaded,\@ifundefined,\@nil,\@secondoftwo}
% \DoNotIndex{\@tempcnta,\@tempcntb,\MessageBreak,\advance,\afterassignment}
% \DoNotIndex{\aftergroup,\begin,\begingroup,\bgroup,\catcode,\csname,\def}
% \DoNotIndex{\divide,\do,\edef,\egroup,\else,\end,\endcsname,\endgroup}
% \DoNotIndex{\expandafter,\fi,\futurelet,\g@addto@macro,\gdef,\global}
% \DoNotIndex{\hbox,\if,\ifcase,\ifnum,\ifx,\immediate,\lccode,\let,\loop}
% \DoNotIndex{\lowercase,\multiply,\newcommand,\noexpand,\or,\relax,\repeat}
% \DoNotIndex{\space,\string,\the,\toks,\uccode,\uppercase,\usepackage}
% \DoNotIndex{\xdef}
%
% ^^A  Define a few logical styles.
% \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}}
% \DeclareRobustCommand{\pkgname}[1]{^^A
%   \mbox{\textsf{#1}}^^A
%   \SortIndex{#1}{\textsf{#1} (package)}^^A
%   \index{packages&#1=\textsf{#1}}^^A
% }
% \DeclareRobustCommand{\clsname}[1]{^^A
%   \mbox{\textsf{#1}}^^A
%   \SortIndex{#1}{\textsf{#1} (class)}^^A
%   \index{classes&#1=\textsf{#1}}^^A
% }
% \makeatletter
% \DeclareRobustCommand{\xmpprop}[2][]{^^A   XMP property
%   \def\xmppropopt{#1}^^A
%   \ifx\xmppropopt\@empty
%     \mbox{\textsf{#2}}^^A
%   \else
%     \mbox{\textsf{#2}}.\mbox{\textsf{#1}}^^A
%     \SortIndex{#1}{\textsf{#1}}^^A
%   \fi
%   \SortIndex{#2}{\textsf{#2}}^^A
%   \index{properties, \acrostyle{XMP}&#2=\textsf{#2}}^^A
% }
% \DeclareRobustCommand{\xmpterm}[1]{^^A     All other XMP terms
%   \mbox{\textsf{#1}}^^A
%   \SortIndex{#1}{\textsf{#1}}^^A
% }
% \makeatother
% \index{XMP=\acrostyle  {XMP}&properties|see{properties, \acrostyle{XMP}}}
% \DeclareRobustCommand{\pdfterm}[1]{^^A
%   \mbox{\textsf{#1}}^^A
%   \SortIndex{#1}{\textsf{#1}}^^A
%   \index{PDF=\acrostyle{PDF}&#1=\textsf{#1}}^^A
% }
% \DeclareRobustCommand{\cmdname}[1]{\mbox{\texttt{#1}}\SortIndex{#1}{\texttt{#1}}}
% \DeclareRobustCommand{\optname}[1]{^^A
%   \mbox{\textsf{#1}}^^A
%   \SortIndex{#1}{\textsf{#1} (option)}^^A
%   \index{options&#1=\textsf{#1}}^^A
% }
% ^^A  \moptname is the same as \optname but additionally typesets the
% ^^A  option name in the margin.
% \DeclareRobustCommand{\moptname}[1]{^^A
%   \optname{#1}^^A
%   \marginpar{\raggedleft\strut\mbox{\textsf{#1}}}^^A
% }
% \DeclareRobustCommand{\acrostyle}[1]{\textsc{\MakeLowercase{#1}}}
% \DeclareRobustCommand{\acro}[1]{^^A
%   \mbox{\acrostyle{#1}}^^A
%   \SortIndex{#1}{\acrostyle{#1}}^^A
% }
% \newcounter{note}
% \newcommand{\usagenote}[1]{^^A
%   \refstepcounter{note}^^A
%   \Needspace{\baselineskip}^^A
%   \belowpdfbookmark{Note \thenote: #1}{note.\thenote}^^A
%   \paragraph{Note~\thenote: #1}%
% }
%
% ^^A  Define some other shortcut macros.
% \DeclareRobustCommand{\tex}{^^A
%   \texorpdfstring{\TeX\SortIndex{TeX}{\TeX}}{TeX}^^A
% }
% \DeclareRobustCommand{\XeTeXlogo}{^^A
%   X\lower0.5ex\hbox{\kern-.15em\reflectbox{E}}\kern-0.1667em\TeX
% }
% \DeclareRobustCommand{\XeTeX}{^^A
%   \texorpdfstring{\XeTeXlogo\SortIndex{XeTeX}{\XeTeXlogo}}{XeTeX}^^A
% }
% \DeclareRobustCommand{\XeLaTeXlogo}{^^A
%   X\lower0.5ex\hbox{\kern-.15em\reflectbox{E}}\kern-0.1667em\LaTeX
% }
% \DeclareRobustCommand{\XeLaTeX}{^^A
%   \texorpdfstring{\XeLaTeXlogo\SortIndex{XeLaTeX}{\XeLaTeXlogo}}{XeLaTeX}^^A
% }
% \DeclareRobustCommand{\LuaTeXlogo}{Lua\TeX}
% \DeclareRobustCommand{\LuaTeX}{^^A
%   \texorpdfstring{\LuaTeXlogo\SortIndex{LuaTeX}{\LuaTeXlogo}}{LuaTeX}^^A
% }
% \DeclareRobustCommand{\LuaLaTeXlogo}{Lua\LaTeX}
% \DeclareRobustCommand{\LuaLaTeX}{^^A
%   \texorpdfstring{\LuaLaTeXlogo\SortIndex{LuaLaTeX}{\LuaLaTeXlogo}}{LuaLaTeX}^^A
% }
% \DeclareRobustCommand{\pdfTeXlogo}{pdf\TeX}
% \DeclareRobustCommand{\pdfTeX}{^^A
%   \texorpdfstring{\pdfTeXlogo\SortIndex{pdfTeX}{\pdfTeXlogo}}{pdfTeX}^^A
% }
% \DeclareRobustCommand{\pdfLaTeXlogo}{pdf\LaTeX}
% \DeclareRobustCommand{\pdfLaTeX}{^^A
%   \texorpdfstring{\pdfLaTeXlogo\SortIndex{pdfLaTeX}{\pdfLaTeXlogo}}{pdfLaTeX}^^A
% }
% \DeclareRobustCommand{\Dvips}{^^A
%   \texorpdfstring{Dvips\SortIndex{dvips}{\texttt{dvips}}}{Dvips}^^A
% }
% \DeclareRobustCommand{\progname}[1]{^^A
%   \mbox{\texttt{#1}}\SortIndex{#1}{\texttt{#1}}^^A
% }
% \DeclareRobustCommand{\Lua}{^^A
%   Lua\index{Lua}^^A
% }
% \DeclareRobustCommand{\Koma}{^^A
%   Koma^^A
%   \SortIndex{Koma}{Koma (class)}^^A
%   \index{classes&Koma}^^A
% }
% \DeclareRobustCommand{\ACMclass}{^^A
%   \acro{ACM}^^A
%   \index{classes&ACM=\acrostyle{ACM}}^^A
% }
%
% ^^A  Define an environment just like macro but for Lua functions.
% \makeatletter
% \newenvironment{luafunc}{^^A
%   \begingroup
%     \catcode`\_=11
%     \def\PrintMacroName##1{\strut\MacroFont\string##1\ }^^A
%     \def\SpecialIndex@##1##2{^^A
%       \@bsphack
%       \special@index{\string##1\actualchar
%         \string\verb\quotechar*\verbatimchar##1\verbatimchar##2}^^A
%       \@esphack
%     }^^A
%     \begin{macro}^^A
% }{^^A
%     \end{macro}^^A
%   \endgroup
% }
% \makeatother
%
% ^^A  Typeset a PDF standard name, indexing only the standard type but
% ^^A  not the subtype or year.
% \makeatletter
% \newcommand*{\PDFstd}[4]{^^A
%   \mbox{^^A
%     \acro{PDF/#1}-\oldstylenums{#2}^^A
%     #3^^A
%     \@ifnotmtarg{#4}{:\oldstylenums{#4}}^^A
%   }^^A
% }
% \makeatother
%
% ^^A  Index schemata.
% \DeleteShortVerb{\|}
% \makeatletter
% \newenvironment{schemadesc}[2][]{^^A
%   \@ifmtarg{#1}{^^A
%     \index{#2 schema|(}^^A
%     \index{schemata&#2|(}^^A
%     \def\closeschemedesc{^^A
%       \index{schemata&#2|)}^^A
%       \index{#2 schema|)}^^A
%     }^^A
%   }{^^A
%     \index{#1 schema=#2 schema|(}^^A
%     \index{schemata&#1=#2|(}^^A
%     \def\closeschemedesc{^^A
%       \index{schemata&#1=#2|)}^^A
%       \index{#1 schema=#2 schema|)}^^A
%     }^^A
%   }^^A
% }{^^A
%   \closeschemedesc
% }
% \newcommand{\schema}[2][]{^^A
%   \@ifmtarg{#1}{^^A
%     \kern0pt^^A
%     \index{#2 schema}^^A
%     \index{schemata&#2}^^A
%     #2^^A
%   }{^^A
%     \kern0pt^^A
%     \index{#1 schema=#2 schema}^^A
%     \index{schemata&#1=#2}^^A
%     #2^^A
%   }^^A
% }
% \makeatother
% \MakeShortVerb{\|}
%
% ^^A  Pack figures a bit tighter onto the page.
% \renewcommand{\floatpagefraction}{0.8}
%
% ^^A  Help \pageref refer to arbitrary content.
% \newcounter{pagelabel}
%
% \maketitle
% \sloppy
%
% \begin{abstract}
%   \pkgname{hyperxmp} makes it easy for an author to include \acro{XMP}
%   metadata in a \acro{PDF} document produced by \LaTeX\@.  \pkgname{hyperxmp}
%   integrates seamlessly with \pkgname{hyperref} and requires virtually
%   no modifications to a document that already specifies document
%   metadata through \pkgname{hyperref}'s mechanisms.
% \end{abstract}
%
% \section{Introduction}
%
% Adobe Systems, Inc.\ has been promoting
% \acro{XMP}~\cite{Adobe2012:XMP}---eXtensible Metadata Platform---as a
% standard way to include metadata within a document.  The idea behind
% \acro{XMP} is that it is an \acro{XML}-based description of various
% document attributes and is embedded as uncompressed, unencoded text
% within the document it describes.  By storing the metadata this way it
% is independent of the document's file format.  That is, regardless of
% whether a document is in \acro{PDF}, \acrostyle{JPEG},
% \acrostyle{HTML}, or any other format, it is trivial for a program (or
% human) to locate, extract, and---using any standard \acro{XML}
% parser---process the embedded \acro{XMP} metadata.
%
% As of this writing there are few tools that actually do process
% \acro{XMP}\@.  However, it is easy to imagine future support existing
% in file browsers for displaying not only a document's filename but
% also its title, list of authors, description, and other metadata.
%
% \paragraph{This is too abstract!  Give me an example.}
% Consider a \LaTeX\ document with three authors---Jack Napier, Edward
% Nigma, and Harvey Dent---named in the \LaTeX\ source in the usual way:
% ``\verb|\author{|\texttt{Jack Napier \cs{and} Edward Nigma \cs{and}
%   Harvey Dent}\verb|}|''.  With \pkgname{hyperxmp}, the generated
% \acro{PDF} file will contain, among other information, the following
% stanza of \acro{XMP} code embedded within it:
%
% \begin{verbatim}
%    <dc:creator>
%      <rdf:Seq>
%        <rdf:li>Jack Napier</rdf:li>
%        <rdf:li>Edward Nigma</rdf:li>
%        <rdf:li>Harvey Dent</rdf:li>
%      </rdf:Seq>
%    </dc:creator>
% \end{verbatim}
%
% In the preceding code, the |dc| namespace refers to the
% \href{http://purl.org/DC/}{\schema{Dublin Core} schema}, a collection
% of metadata properties.  The \xmpprop{dc:creator} property surrounds
% the list of authors.  The \textsf{rdf} namespace is the
% \href{http://www.w3.org/RDF/}{Resource Description Framework}, which
% defines \xmpterm{rdf:Seq} as an ordered list of values.  Each author
% is represented by an individual list item (\xmpterm{rdf:li}), making
% it easy for an \acro{XML} parser to separate the authors' names.
%
% Remember that \acro{XMP} code is stored as \emph{metadata}.  It does
% not appear when viewing or printing the \acro{PDF} file.  Rather, it
% is intended to make it easy for computer applications to identify and
% categorize the document.
%
% \subsection{Supported metadata}
%
% \pkgname{hyperxmp} knows how to embed all of the following types of
% metadata within a document:
%
% \label{page:begin-metadata-list}
% \begin{itemize} \raggedright
%   \item address of primary author
%     (\xmpprop[CiAdrExtadr]{Iptc4xmpCore:CreatorContactInfo},
%     \xmpprop[CiAdrCity]{Iptc4xmpCore:CreatorContactInfo},
%     \xmpprop[CiAdrRegion]{Iptc4xmpCore:CreatorContactInfo},
%     \xmpprop[CiAdrPcode]{Iptc4xmpCore:CreatorContactInfo}, and
%     \xmpprop[CiAdrCtry]{Iptc4xmpCore:CreatorContactInfo})
%   \item author(s) (\xmpprop{dc:creator})
%   \item base \acro{URL} for relative references (\xmpprop{xmp:BaseURL})
%   \item book edition (\xmpprop{prism:bookEdition})
%   \item copyright (\xmpprop{dc:rights} and \xmpprop{xmpRights:Marked})
%   \item date (\xmpprop{dc:date}, \xmpprop{xmp:CreateDate},
%     \xmpprop{xmp:ModifyDate}, and \xmpprop{xmp:MetadataDate})
%   \item \acro{DOI} (\xmpprop{prism:doi})
%   \item email address(es) of primary author (\xmpprop[CiEmailWork]{Iptc4xmpCore:CreatorContactInfo})
%   \item file format (\xmpprop{dc:format})
%   \item file name of main \LaTeX\ source file (\xmpprop{dc:source})
%   \item file size in bytes (\xmpprop{prism:byteCount})
%   \item \acro{ISBN} (\xmpprop{prism:isbn})
%   \item \acro{ISSN}---both print (\xmpprop{prism:issn}) and electronic (\xmpprop{prism:eIssn})
%   \item issue number of parent publication (\xmpprop{prism:number})
%   \item journal article version (\xmpprop{jav:journal\_article\_version})
%   \item keywords (\xmpprop{pdf:Keywords} and \xmpprop{dc:subject})
%   \item language used (\xmpprop{dc:language})
%   \item license \acro{URL} (\xmpprop{xmpRights:WebStatement})
%   \item metadata writer (\xmpprop{photoshop:CaptionWriter})
%   \item page count (\xmpprop{prism:pageCount})
%   \item page range(s) (\xmpprop{prism:pageRange})
%   \item \acro{PDF} version (\xmpprop{pdf:PDFVersion})
%   \item \acro{PDF}-generating tool (\xmpprop{pdf:Producer} and \xmpprop{xmp:CreatorTool})
%   \item \acro{PDF/A} version and conformance level (\xmpprop{pdfaid:part} and \xmpprop{pdfaid:conformance})
%   \item \acro{PDF/UA} version (\xmpprop{pdfuaid:part})
%   \item \acro{PDF/X} standard compliance (\xmpprop{pdfxid:GTS\_PDFXVersion})
%   \item position/title of primary author (\xmpprop{photoshop:AuthorsPosition})
%   \item publication name of parent publication (\xmpprop{prism:publicationName})
%   \item publisher of the document (\xmpprop{dc:publisher})
%   \item rendition variation of the document (\xmpprop{xmpMM:RenditionClass})
%   \item summary (\xmpprop{dc:description})
%   \item subtitle (\xmpprop{prism:subtitle})
%   \item telephone number(s) of primary author (\xmpprop[CiTelWork]{Iptc4xmpCore:CreatorContactInfo})
%   \item title (\xmpprop{dc:title})
%   \item trapping of colors (\xmpprop{pdf:trapped})
%   \item type of document (\xmpprop{dc:type})
%   \item type of parent publication (\xmpprop{prism:aggregationType})
%   \item unique identifier for the document (\xmpprop{dc:identifier})
%   \item \acro{URL} of the document (\xmpprop{prism:url})
%   \item \acro{URL}(s) of the primary author (\xmpprop[CiUrlWork]{Iptc4xmpCore:CreatorContactInfo})
%   \item \acro{UUID} for the document (\xmpprop{xmpMM:DocumentID})
%   \item \acro{UUID} for the document instance (\xmpprop{xmpMM:InstanceID})
%   \item version identifier for the document (\xmpprop{xmpMM:VersionID})
%   \item volume number of parent publication (\xmpprop{prism:volume})
% \end{itemize}
% \label{page:end-metadata-list}
%
% \noindent
% More types of metadata may be added in a future release.
%
% \subsection{Comparisons with similar packages}
%
% \paragraph{\textsf{xmpincl}}
% In short, \pkgname{xmpincl} is more flexible but \pkgname{hyperxmp} is
% easier to use.  With \pkgname{xmpincl}, the author manually constructs
% a file of arbitrary \acro{XMP} data and the package merely embeds it
% within the generated \acro{PDF} file.  With \pkgname{hyperxmp}, the
% author specifies values for various predefined metadata types and the
% package formats those values as \acro{XMP} and embeds the result
% within the generated \acro{PDF} file.
%
% \pkgname{xmpincl} can embed \acro{XMP} only when running under \pdfLaTeX\ and
% only when in \acro{PDF}-generating mode.  \pkgname{hyperxmp} additionally
% works with a few other \acro{PDF}-producing \LaTeX\ backends.
%
% \pkgname{hyperxmp} and \pkgname{xmpincl} can complement each other.
% An author may want to use \pkgname{hyperxmp} to produce a basic set of
% \acro{XMP} code, then extract the \acro{XMP} code from the \acro{PDF} file with a text
% editor, augment the \acro{XMP} code with any metadata not supported by
% \pkgname{hyperxmp}, and use \pkgname{xmpincl} to include the modified
% \acro{XMP} code in the \acro{PDF} file.
%
% \paragraph{\textsf{pdfx}}
% The main difference between \pkgname{hyperxmp} and \pkgname{pdfx} is
% that \pkgname{hyperxmp} tries to integrate as seamlessly as possible
% into an existing document.  It leverages \pkgname{hyperref}'s
% \cs{hypersetup} command and many of \cs{hypersetup}'s options and
% defines its own options in a compatible manner.  In contrast,
% \pkgname{pdfx} requires the user to create a separate
% |\jobname.xmpdata| file containing \pkgname{pdfx}-defined commands for
% each metadata element.
%
% \iffalse
%<*listings>
% \fi
\newsavebox{\pdfxbox}
\begin{lrbox}{\pdfxbox}
  \begin{lstlisting}[
      language=tex,
      columns=fullflexible,
      linewidth=14pc,
      frame=single,
      basicstyle=\footnotesize,
      showlines,
      morekeywords={\Title,\Author,\Language,\Keywords,\Publisher,\sep}
    ]

\Title{Baking through the ages}
\Author{A. Baker\sep C. Kneader}
\Language{en-GB}
\Keywords{cookies\sep muffins\sep cakes}
\Publisher{Baking International}

  \end{lstlisting}
\end{lrbox}

\newsavebox{\hyxmpbox}
\begin{lrbox}{\hyxmpbox}
  \begin{lstlisting}[
      language=tex,
      columns=fullflexible,
      linewidth=13pc,
      frame=single,
      basicstyle=\footnotesize,
      morekeywords={\hypersetup}
    ]
\hypersetup{%
  pdftitle={Baking through the ages},
  pdfauthor={A. Baker, C. Kneader},
  pdflang={en-GB},
  pdfkeywords={cookies, muffins, cakes},
  pdfpublisher={Baking International}
}
  \end{lstlisting}
\end{lrbox}
% \iffalse
%</listings>
% \fi
%
% Figure~\ref{fig:pdfx-hyxmp} adapts an example appearing in the
% \pkgname{pdfx} manual to \pkgname{hyperxmp}.
% \begin{figure}
%   \centering
%   \subcaptionbox{\pkgname{pdfx} (separate \texttt{.xmpdata} file)
%     \label{fig:ph-pdfx}}{%
%     \usebox{\pdfxbox}%
%   }
%   \hfil
%   \subcaptionbox{\pkgname{hyperxmp} (main document)
%     \label{fig:ph-hyxmp}}{%
%     \usebox{\hyxmpbox}}
%   \caption{Comparison of \pkgname{pdfx} and \pkgname{hyperxmp}}
%   \label{fig:pdfx-hyxmp}
% \end{figure}
% The two are comparable line-by-line in terms of how one specifies the
% title, author, document language, keywords, and publisher.  However,
% \pkgname{hyperxmp} implicitly writes a wealth of additional metadata
% into the \acro{XMP} packet such as the document date, creation date,
% creator tool, file format, \acro{PDF} version, and unique document and
% instance IDs.  In fact, if a document omits all of the code shown in
% Figure~\ref{fig:ph-hyxmp}, it will still store the \cs{title} and
% \cs{author} data in the \acro{XMP} packet.
%
% One can therefore summarize the difference between \pkgname{hyperxmp}
% and \pkgname{pdfx} as follows: \pkgname{pdfx} requires the author to
% be fully explicit about the document's metadata while
% \pkgname{hyperxmp} allows some metadata to be specified implicitly,
% automatically inferring it when possible.  In general,
% \pkgname{hyperxmp} tries to simplify the author's task as much as
% possible.
%
%
% \section{Usage}
%
% \pkgname{hyperxmp} works by postprocessing some of the package options
% honored by \pkgname{hyperref}.  To use \pkgname{hyperxmp}, merely put
% a |\usepackage{hyperxmp}| in your document's preamble.  That line can
% appear anywhere before the \pkgname{hyperref} \acro{PDF} options are
% specified (i.e.,~with either |\usepackage[|\dots|]{hyperref}| or
% |\hypersetup{|\dots|}|).  \pkgname{hyperxmp} will construct its
% \acro{XMP} data using the following \pkgname{hyperref} options:
%
% \begin{multicols}{3}
%   \raggedcolumns
%   \begin{itemize}
%   \item \optname{baseurl}
%   \item \optname{pdfauthor}
%   \item \optname{pdfcreationdate}
%   \item \optname{pdfkeywords}
%   \item \optname{pdflang}
%   \item \optname{pdfmoddate}
%   \item \optname{pdfproducer}
%   \item \optname{pdfsubject}
%   \item \optname{pdftitle}
%   \item \optname{pdftrapped}
%   \end{itemize}
% \end{multicols}
%
% \noindent
% \mbox{}\label{page:begin-new-options}
% \pkgname{hyperxmp} instructs \pkgname{hyperref} also to accept the
% following options, which have meaning only to \pkgname{hyperxmp}:
%
% \begin{multicols}{3}
%   \raggedcolumns
%   \begin{itemize}
%   \item \optname{pdfaconformance}
%   \item \optname{pdfapart}
%   \item \optname{pdfauthortitle}
%   \item \optname{pdfbookedition}
%   \item \optname{pdfbytes}
%   \item \optname{pdfcaptionwriter}
%   \item \optname{pdfcontactaddress}
%   \item \optname{pdfcontactcity}
%   \item \optname{pdfcontactcountry}
%   \item \optname{pdfcontactemail}
%   \item \optname{pdfcontactphone}
%   \item \optname{pdfcontactpostcode}
%   \item \optname{pdfcontactregion}
%   \item \optname{pdfcontacturl}
%   \item \optname{pdfcopyright}
%   \item \optname{pdfdate}
%   \item \optname{pdfdocumentid}
%   \item \optname{pdfdoi}
%   \item \optname{pdfeissn}
%   \item \optname{pdfidentifier}
%   \item \optname{pdfinstanceid}
%   \item \optname{pdfisbn}
%   \item \optname{pdfissn}
%   \item \optname{pdfissuenum}
%   \item \optname{pdflicenseurl}
%   \item \optname{pdfmetadate}
%   \item \optname{pdfmetalang}
%   \item \optname{pdfnumpages}
%   \item \optname{pdfpagerange}
%   \item \optname{pdfpublication}
%   \item \optname{pdfpublisher}
%   \item \optname{pdfpubstatus}
%   \item \optname{pdfpubtype}
%   \item \optname{pdfrendition}
%   \item \optname{pdfsource}
%   \item \optname{pdfsubtitle}
%   \item \optname{pdftype}
%   \item \optname{pdfuapart}
%   \item \optname{pdfurl}
%   \item \optname{pdfversionid}
%   \item \optname{pdfvolumenum}
%   \item \optname{pdfxstandard}
%   \end{itemize}
% \end{multicols}
% \label{page:end-new-options}
%
%
% \subsection{Option descriptions}
%
% The document title is specified as normal for \pkgname{hyperref} with
% \moptname{pdftitle}, but see Note~\ref{note:multilingual} on
% page~\pageref{note:multilingual} for instructions on how to specify a
% title in multiple languages.  If \optname{pdftitle} is not specified
% it will inherit its value from the document's \cs{title}.
% \pkgname{hyperxmp} introduces a complementary \moptname{pdfsubtitle}
% option:
%
% \begin{verbatim}
%   pdftitle={Frankenstein},
%   pdfsubtitle={The Modern Prometheus},
% \end{verbatim}
%
% Unfortunately, the subtitle can appear in only one language.  It
% assumed to be the same language as the document language
% (\optname{pdflang}) but can be overridden by preceding the text with a
% bracketed \acro{ISO} \mbox{639-1} two-letter language code and an
% optional \acro{ISO} \mbox{3166-1} two-letter region code.  See the
% example below for \optname{pdfpublication}.
%
% \pkgname{hyperref}'s \moptname{pdfauthor} option specifies the
% document's author(s).  See Note~\ref{note:literal-commas} on
% page~\pageref{note:literal-commas} for a discussion of the correct
% syntax.  If \optname{pdfauthor} is not specified it will inherit its
% value from the document's \cs{author}.  \moptname{pdfauthortitle}
% indicates the primary author's position or title.
% \moptname{pdfcaptionwriter} specifies the name of the person who added
% the metadata to the document.
%
% The next eight items describe how to contact the person or institution
% responsible for the document (the ``contact'').
% \moptname{pdfcontactaddress} is the contact's street address and can
% include the institution name if the contact is an institution;
% \moptname{pdfcontactcity} is the contact's city;
% \moptname{pdfcontactcountry} is the contact's country;
% \moptname{pdfcontactemail} is the contact's email address (or
% multiple, comma-separated email addresses); \moptname{pdfcontactphone}
% is the contact's telephone number (or multiple, comma-separated
% telephone numbers); \moptname{pdfcontactpostcode} is the contact's
% postal code; \moptname{pdfcontactregion} is the contact's state or
% province; and \moptname{pdfcontacturl} is the contact's \acro{URL} (or
% multiple, comma-separated \acro{URL}s).
%
% \Needspace{2\baselineskip}
% \moptname{pdfcopyright} defines the copyright text, and
% \moptname{pdflicenseurl} identifies a \acro{URL} that points to the
% document's license agreement.
%
% \moptname{pdfmetalang} indicates the natural language in which certain
% metadata---specifically, the document's title, subject, and copyright
% statement---are written.  The language should be specified using an
% \acro{IETF} language tag~\cite{IANA2011:lang-tags}, for example,
% ``|en|'' for English, ``|en-US|'' for specifically United States
% English, ``|de|'' for German, and so forth.  If \optname{pdfmetalang}
% is not specified, \pkgname{hyperxmp} assumes the metadata language is
% the same as the document language (\pkgname{hyperref}'s
% \moptname{pdflang} option).  If neither \optname{pdfmetalang} nor
% \optname{pdflang} is specified, \pkgname{hyperxmp} uses only
% ``\xmpterm{x-default}'' as the metadata language.
%
% \acro{XMP} can include a universally unique identifier (\acro{UUID})
% for each document and for each instance of a given document.  By
% default, \pkgname{hyperxmp} assigns a version~4 (i.e.,~pseudorandom)
% \acro{UUID}~\cite{Leach2005:uuid} for each of these.  However, a
% document can alternatively specify a particular document identifier
% using \moptname{pdfdocumentid} and (not normally recommended) a
% particular instance identifier using \moptname{pdfinstanceid}.  These
% should be of the form
% \texttt{uuid:}\textit{xxxxxxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxxxxxxxxxx},
% where ``\textit{x}'' is a lowercase hexadecimal number.  For example,
% \texttt{uuid:53ab7f19-a48c-5177-8bb2-403ad907f632} is a valid argument
% to \optname{pdfdocumentid} (or \optname{pdfinstanceid}).  See Leach,
% Mealling, and Salz's \acro{UUID} specification document for details on
% how to produce the various forms of
% \acro{UUID}s~\cite{Leach2005:uuid}.  A more freeform mechanism than
% \optname{pdfinstanceid} for versioning documents is available via
% \moptname{pdfversionid}.  The version specified by
% \optname{pdfversionid} can be incremented as~|1|, |2|, |3|,~\dots;
% identified with a hierarchical numbering scheme (e.g.,~this document
% is versioned \texttt{\versionnumber} to match the package version); or
% labeled using any other approach.  One possibility is to use a
% revision number or commit hash from the version-control software
% maintaining the document.  For example, the |\gitVer| macro from the
% \pkgname{gitver} package is an expandable (see
% Note~\ref{note:expandable} on page~\pageref{note:expandable}) version
% of the current \href{https://git-scm.com/}{Git} hash that can suitably
% be passed to \optname{pdfversionid}.  If not specified,
% \optname{pdfversionid} defaults to~|1|.
%
% Already-published documents can be identified in a number of ways.
% \moptname{pdfisbn} specifies the \acro{ISBN}.  \moptname{pdfissn}
% refers to the \acro{ISSN} of the \emph{print} version of the document
% while \moptname{pdfeissn} refers to the \acro{ISSN} of the
% \emph{electronic} version of the document.  \moptname{pdfdoi}
% specifies the \acro{DOI} and should include only the \acro{DOI} name
% without any \acro{URL} prefix.  For example, specify
% |pdfdoi={10.1145/3149526.3149532}|, \emph{not}
% |pdfdoi={https://doi.org/10.1145/3149526.3149532}|.
% \moptname{pdfurl} points to the complete \acro{URL} for the document.
% In contrast, \moptname{baseurl} points one level up and is used to
% resolve relative \acro{URL}s.
%
% \moptname{pdfidentifier} provides an alternative mechanism to uniquely
% identify a document.  Its advantage relative to \optname{pdfisbn},
% \optname{pdfissn}, \optname{pdfdoi}, etc.\ is its flexibility; any of
% a wide variety of identification types can be used.\footnote{See, for
%   example,
%   \url{https://www.iana.org/assignments/urn-namespaces/urn-namespaces.xhtml}
%   for the \texttt{urn:} \acro{URI} scheme and
%   \url{http://info-uri.info/registry/} for the \texttt{info:}
%   \acro{URI} scheme.}  \optname{pdfidentifier}'s disadvantage is that
% it allows only a single identifier per document.  For example, a
% document could use |pdfidentifier=urn:iso:std:32000:ed-1:v1:en| to
% identify itself as version~1 of English-language \acro{ISO} standard
% 32000-1, but then this same document could not also use
% \optname{pdfidentifier} to identify itself by \acro{DOI}
% (|info:doi/|\dots), \acro{ISBN} (|urn:ISSN:|\dots), etc.  (It can
% still use the options described in the previous paragraph, though.)  If
% \optname{pdfidentifier} is not specified explicitly,
% \pkgname{hyperxmp} will use the first non-empty value out of the
% \acro{DOI}, electronic \acro{ISSN}, print \acro{ISSN}, and \acro{ISBN}
% or skip the identifier entirely if all of those are empty.
%
% Already-published documents can further be identified by the
% publication in which they appear.  \moptname{pdfpublication} specifies
% the title of the journal, magazine, or other parent document.  The
% title language is assumed to be the same as the document language
% (\optname{pdflang}) but can be overridden by preceding the text with a
% bracketed \acro{ISO} \mbox{639-1} two-letter language code and an
% optional \acro{ISO} \mbox{3166-1} two-letter region code.  For
% example, |pdfpublication={[fr]Charlie Hedbo}| indicates a
% French-language title.  Were the language or pronunciation differences
% significant, |fr-FR| would indicate specifically the French spoken in
% France, as opposed to that spoken in, say, Canada (|fr-CA|) or Belgium
% (|fr-BE|).  The publisher itself can be named using
% \moptname{pdfpublisher}.
%
% \moptname{pdfpubtype} indicates the type of publication in which the
% document was published.  This should be one of the \acro{PRISM}
% aggregation types~\cite{PRISM2012:cont-voc} such as |book|, |journal|,
% |magazine|, |manual|, |report|, or |whitepaper|.
%
% For publications in journals, magazines, and similar periodicals, a
% document can specify the volume number with \moptname{pdfvolumenum}
% and the issue number within the volume with \moptname{pdfissuenum}.
% \moptname{pdfpagerange} indicates the page numbers at which the
% document appears within the publication.  The intention is that this
% be a comma-separated list of dash-separated ranges, as in
% |pdfpagerange={1,4-5}|.  See Note~\ref{note:page-counting} on
% page~\pageref{note:page-counting} for advice on how to assign
% \optname{pdfpagerange} semi-automatically.  A journal article's
% publication status can be indicated with \moptname{pdfpubstatus}.
% This option expects to take one of the values listed in
% Table~\ref{tbl:jav}.  See the \acro{NISO}/\acro{ALPSP} Journal Article
% Versions recommendation~\cite{NISO2008:jav} for an explanation of each
% of those values and when to use them.
%
% \begin{table}
%   \centering
%   \caption{Valid arguments for \optname{pdfpubstatus}}
%   \label{tbl:jav}
%   \begin{tabular}{@{}>{\ttfamily}ll@{}}
%   \toprule
%   \multicolumn{1}{@{}l}{Value} & Meaning \\
%   \midrule
%   AO   & Author's Original \\
%   SMUR & Submitted Manuscript Under Review \\
%   AM   & Accepted Manuscript \\
%   P    & Proof \\
%   VoR  & Version of Record \\
%   CVoR & Corrected Version of Record \\
%   EVoR & Enhanced Version of Record \\
%   \bottomrule
%   \end{tabular}
% \end{table}
%
% For books, \moptname{pdfbookedition} names the edition of the book.
% This is specified as text, not a number.  As with
% \optname{pdfpublication} (above), \optname{pdfbookedition} accepts a
% bracketed language code, as in |pdfbookedition={[en]Second|
%   |edition}|.
%
% \acro{XMP} metadata can include a number of dates (in fact,
% timestamps, as they include both date and time components).
% \moptname{pdfdate} specifies the document date.  It is analogous to the
% \LaTeX\ |\date| command, and, like |\date|, defaults to the date the
% document was built.  It must be specified in either \acro{XMP}
% format~\cite{Adobe2012:XMP} or \acro{PDF} format~\cite{Adobe2008:PDF}.
% \acro{XMP} dates are written in the form
% \textsc{yyyy}|-|\textsc{mm}|-|\textsc{dd}|T|hh|:|mm|:|ss|+|\textsc{tt}|:|tt.\footnote{Although
%   allowed by \acro{XMP}, \pkgname{hyperxmp} does not currently accept
%   fractions of a second in timestamps.}  A W3C
% recommendation~\cite{Wolf1997:date-time} discusses this format in more
% detail, but as an example, 14~hours, 15~minutes, 9~seconds past
% midnight U.S. Mountain Daylight Time (UTC-6) on the 23rd day of
% September in the year~2014 should be written as
% \texttt{2014-09-23T14:15:09-06:00}.  This can be truncated (with loss
% of information) to \texttt{2014-09-23T14:15:09},
% \texttt{2014-09-23T14:15}, \texttt{2014-09-23}, \texttt{2014-09},
% or \texttt{2014} but no other subsets.  \acro{PDF} dates are written
% in the form |D:|\textsc{yyyymmdd}hhmmss|+|\textsc{tt}|'|tt|'|.  The
% same date in the preceding example would be written as
% \texttt{D:20140923141509-06'00'} in \acro{PDF} format.
%
% The document's creation date, modification date, and metadata date are
% normally set automatically, but \moptname{pdfcreationdate},
% \moptname{pdfmoddate}, and \moptname{pdfmetadate} can be used to
% override the defaults.  Like \optname{pdfdate}, \optname{pdfmetadate}
% can be specified in either \acro{XMP} or \acro{PDF} format.  However,
% because \pkgname{hyperref} defines \optname{pdfcreationdate} and
% \optname{pdfmoddate} and expects these to be written as \acro{PDF}
% dates, \pkgname{hyperxmp} concomitantly accepts these two dates only
% in \acro{PDF} format as well.  Note that it's rare that a document
% would need to specify any of \optname{pdfcreationdate},
% \optname{pdfmoddate}, or \optname{pdfmetadate}.
%
% \moptname{pdftype} describes the type of document being produced.
% This refers to ``the nature or genre of the
% resource''~\cite{Adobe2012:XMP} such as |poem|, |novel| or |working|
% |paper|, as opposed to the file format (always |application/pdf| when
% generated by \pkgname{hyperxmp}).  Although \optname{pdftype} can be
% assigned an arbitrary piece of text, the \acro{XMP} specification
% recommends selecting types from a ``controlled vocabulary'' such as
% the \acro{DCMI} Type Vocabulary~\cite{DCMI2012:meta-terms}.  The
% \acro{DCMI} Type Vocabulary currently consists of only |Collection|,
% |Dataset|, |Event|, |Image|, |InteractiveResource|, |MovingImage|,
% |PhysicalObject|, |Service|, |Software|, |Sound|, |StillImage|, and
% |Text|.  \optname{pdftype} defaults to |Text|, which refers to
% ``books, letters, dissertations, poems, newspapers, articles, archives
% of mailing lists,''~\cite{DCMI2012:meta-terms} and other forms of
% text---all things \LaTeX\ is commonly used to typeset.
%
% Sometimes a base document is rendered in different forms.
% \moptname{pdfrendition} indicates the particular rendition the current
% document instance represents.  The value should come from the
% following controlled vocabulary~\cite{Adobe2012:XMP}: |default|,
% |draft|, |low-res|, |proof|, |screen|, and |thumbnail|.
% \pkgname{hyperxmp}'s default value is |default|, which indicates the
% master document, unless the \optname{draft} option is passed to
% |\documentclass|, in which case \pkgname{hyperxmp} defaults to
% |draft|.
%
% \pkgname{hyperxmp} honors \pkgname{hyperref}'s \moptname{pdftrapped}
% option.  A document can indicate whether it employs
% \href{https://en.wikipedia.org/wiki/Trap_(printing)}{color trapping}
% by specifying \optname{pdftrapped}=|True| or
% \optname{pdftrapped}=|False|.  (\optname{pdftrapped}=|Unknown| is also
% allowed.)
%
% \moptname{pdfapart} and \moptname{pdfaconformance}, are used in
% conjunction with \pkgname{hyperref}'s \optname{pdfa} option to claim a
% particular \acro{PDF/A} standard by which the document abides.  They
% default to \optname{pdfapart}=|1| and \optname{pdfaconformance}=|B|,
% indicating the \PDFstd{A}{1}{b}{} standard.  These can be changed
% (with caution) to assert that the document abides by a different
% standard (e.g.,~\PDFstd{A}{2}{u}{}).  A document that conforms to the
% \acro{PDF/UA} standard can use \moptname{pdfuapart} to indicate the
% \acro{PDF/UA} conformance level.  For example, \optname{pdfuapart}=|1|
% asserts that the document respects \PDFstd{UA}{1}{}{}.
% \moptname{pdfxstandard} indicates the particular \acro{PDF/X} standard
% by which the document abides.  Unlike \optname{pdfapart} and
% \optname{pdfaconformance}, which accept a number and a letter,
% respectively, \optname{pdfxstandard} expects a textual identification
% of a standard name.  The following are the acceptable \acro{PDF/X}
% standard names as of at the time of this writing.
%
% ^^A  This list needs to be kept up-to-date with the standards checked
% ^^A  by \@pdfxstandard.
% \begin{multicols}{3}
%   \raggedcolumns
%   \begin{itemize}[noitemsep]
%   \item \PDFstd{X}{1}{a}{2001}
%   \item \PDFstd{X}{1}{a}{2003}
%   \item \PDFstd{X}{3}{}{2002}
%   \item \PDFstd{X}{3}{}{2003}
%   \item \PDFstd{X}{4}{}{}
%   \item \PDFstd{X}{4}{p}{}
%   \item \PDFstd{X}{5}{g}{}
%   \item \PDFstd{X}{5}{n}{}
%   \item \PDFstd{X}{5}{pg}{}
%   \end{itemize}
% \end{multicols}
%
% For example, one can specify \optname{pdfxstandard}=|{PDF/X-4}| or
% \optname{pdfxstandard}=|{PDF/X-3:2003}|, but specifying
% \optname{pdfxstandard}=|{PDF/X-3}| will not pass \acro{PDF/X}
% validation.  Note that at the time of this writing the use of the
% \PDFstd{X}{4}{p}{}, \PDFstd{X}{5}{n}{}, and \PDFstd{X}{5}{pg}{}
% standards has not been tested.
%
% \subsubsection*{Rarely needed options}
%
% \moptname{pdfsource} overrides the name of the \LaTeX\ source file.
% It defaults to |\jobname.tex| but can be replaced by any other string.
% If \optname{pdfsource} is given an empty argument, no document source
% will be specified at all.
%
% The number of pages in the published, print version of the document
% can be expressed with \moptname{pdfnumpages}.  This is computed
% automatically when the document is built using either \pdfLaTeX\ or
% \LuaLaTeX\@.
%
% The \moptname{pdfbytes} option expresses the document's file size in
% bytes.  The intention is for this to be used to display an estimate of
% download time to a user or to serve as a quick check on whether a file
% was transmitted correctly between systems.  \optname{pdfbytes} is
% computed automatically by both \pdfLaTeX\ and \LuaLaTeX, using the
% file size from the previous build of the document.
%
% \bigskip
%
% It is usually more convenient to provide values for all of the options
% presented in this section using \pkgname{hyperref}'s |\hypersetup|
% command than on the |\usepackage| command line.  See
% \href{http://mirrors.ctan.org/macros/latex/contrib/hyperref/hyperref.pdf}{the
%   \pkgname{hyperref} manual} for more information.
%
%
% \subsection{A complete example}
%
% The following is a sample \LaTeX\ document that provides values for
% most of the metadata options that \pkgname{hyperxmp} recognizes:
%
% \Needspace{4\baselineskip}
% \refstepcounter{pagelabel}
% \label{page:begin-sample-doc}
% \begin{verbatim}
%    \documentclass{article}
%    \usepackage[utf8]{inputenc}
%    \usepackage{hyperxmp}
%    \usepackage[unicode]{hyperref}
%
%    \title{%
%      On a heuristic viewpoint concerning the production and
%      transformation of light}
%    \author{Albert Einstein}
%    \date{March 17, 1905}
%
%    \hypersetup{%
%      pdftitle={%
%        On a heuristic viewpoint concerning the production and
%        transformation of light},
%      pdfsubtitle={[en-US]Putting that bum Maxwell in his place},
%      pdfauthor={Albert Einstein},
%      pdfauthortitle={\xmpquote{Technical Assistant\xmpcomma\ Level III}},
%      pdfdate={1905-03-17},
%      pdfcopyright={Copyright (C) 1905, Albert Einstein},
%      pdfsubject={photoelectric effect},
%      pdfkeywords={energy quanta, Hertz effect, quantum physics},
%      pdflicenseurl={http://creativecommons.org/licenses/by-nc-nd/3.0/},
%      pdfcaptionwriter={Scott Pakin},
%      pdfcontactaddress={Kramgasse 49},
%      pdfcontactcity={Bern},
%      pdfcontactpostcode={3011},
%      pdfcontactcountry={Switzerland},
%      pdfcontactphone={031 312 00 91},
%      pdfcontactemail={aeinstein@ipi.ch},
%      pdfcontacturl={%
%        http://einstein.biz/,
%        https://www.facebook.com/AlbertEinstein
%      },
%      pdfdocumentid={uuid:6d1ac9ec-4ff2-515a-954b-648eeb4853b0},
%      pdfversionid={2.998e8},
%      pdfpublication={[de]Annalen der Physik},
%      pdfpublisher={Wiley-VCH},
%      pdfpubtype={journal},
%      pdfvolumenum={322},
%      pdfissuenum={6},
%      pdfpagerange={132-148},
%      pdfissn={0003-3804},
%      pdfeissn={1521-3889},
%      pdfpubstatus={VoR},
%      pdflang={en},
%      pdfmetalang={en},
%      pdfurl={http://www.physik.uni-augsburg.de/annalen/history/einstein-papers/1905_17_132-148.pdf},
%      pdfdoi={10.1002/andp.19053220607},
%      pdfidentifier={info:lccn/50013519}
%    }
%    \XMPLangAlt{de}{pdftitle={Über einen die Erzeugung und Verwandlung des
%      Lichtes betreffenden heuristischen Gesichtspunkt}}
%
%    \begin{document}
%    \maketitle
%    A profound formal difference exists between the theoretical
%    concepts that physicists have formed about gases and other
%    ponderable bodies, and Maxwell's theory of electromagnetic
%    processes in so-called empty space\dots
%    \end{document}
% \end{verbatim}
% \refstepcounter{pagelabel}
% \label{page:end-sample-doc}
%
% Compile the document to \acro{PDF} using any of the following
% approaches:
%
% \begin{itemize}
%   \item \pdfLaTeX
%   \item \LuaLaTeX
%   \item \XeLaTeX
%   \item \LaTeX~$+$ \term{Dvipdfm}
%   \item \LaTeX~$+$ \Dvips~$+$ \term{Ghostscript}
%   \item \LaTeX~$+$ \Dvips~$+$ Adobe Acrobat Distiller
% \end{itemize}
%
% \noindent
% The \LaTeX~$+$ \Dvips~$+$ \term{Ghostscript} path stores the
% \acro{XMP} packet in a compressed stream, which implies that a
% \acro{PDF} reader is needed to access it.  Ideally, \acro{XMP}
% metadata should be stored uncompressed so it can be extracted as
% ordinary text.  Unfortunately, as of 2022-10-07, Ghostscript has no
% plans to support uncompressed metadata streams
% (\href{https://bugs.ghostscript.com/show_bug.cgi?id=705962}{Ghostscript
%   bug report~\#705962}).  It is possible to leave \emph{all} streams
% uncompressed by passing |-dCompressStreams=false| to \term{Ghostscript}
% (e.g.,~via the \progname{ps2pdf} wrapper script), but this leads to
% larger file sizes.
%
% \bigskip
%
% Once the document is compiled, the resulting \acro{PDF} file will
% contain an \acro{XMP} packet that looks something like that shown in
% Appendix~\ref{sec:sample-packet}.  Figure~\ref{fig:xmp-metadata-1} is
% a screenshot of the \acro{XMP} metadata as it appears in Adobe
% Acrobat's ``Advanced'' metadata dialog box.  Further clicking on the
% ``Advanced'' item within that dialog box displays all of the
% document's metadata sorted by schema as shown in
% Figure~\ref{fig:xmp-metadata-2}.
%
% \begin{figure}[htbp]
%   \includegraphics[width=\linewidth]{einstein1}
%   \caption{\acro{XMP} metadata as it appears in Adobe Acrobat}
%   \label{fig:xmp-metadata-1}
% \end{figure}
%
% \begin{figure}[htbp]
%   \includegraphics[width=\linewidth]{einstein2}
%   \caption{Additional \acro{XMP} metadata as it appears in Adobe Acrobat}
%   \label{fig:xmp-metadata-2}
% \end{figure}
%
%
% \subsection{Usage notes}
%
% \usagenote{Conflicting metadata in PDF/A documents}
% \label{note:meta-conflicts}
% A \acro{PDF} file includes an \pdfterm{Info} dictionary containing
% \pdfterm{Author}, \pdfterm{Title}, \pdfterm{Subject}, and
% \pdfterm{Keywords} keys.  The \pkgname{hyperref} package's
% \optname{pdfauthor}, \optname{pdftitle}, \optname{pdfsubject}, and
% \optname{pdfkeywords} options assign values to those keys.  The
% \pkgname{hyperxmp} package additionally uses those options to assign
% values to various \acro{XMP} metadata: \xmpprop{dc:creator},
% \xmpprop{dc:title}, \xmpprop{dc:description}, and
% \xmpprop{pdf:Keywords}.  The \acro{PDF/A} specification indicates that
% values that appear in both the \acro{PDF} \pdfterm{Info} dictionary
% and \acro{XMP} packet must match.  The problem is that in \acro{XMP},
% the author and keywords can be proper lists, as in
%
% \Needspace{7\baselineskip}
% \begin{verbatim}
%     <dc:creator>
%       <rdf:Seq>
%         <rdf:li>Curly Howard</rdf:li>
%         <rdf:li>Larry Fine</rdf:li>
%         <rdf:li>Moe Howard</rdf:li>
%       </rdf:Seq>
%     </dc:creator>
% \end{verbatim}
%
% \noindent
% while in \acro{PDF}, the author and keywords are specified as flat
% strings.  Alas, there is no definition of how a list should be
% collapsed to a flat string: ``\texttt{Curly Howard, Larry Fine, Moe
%   Howard}'' or ``\texttt{Curly Howard; Larry Fine; Moe Howard}'' or
% something else.  I have not yet found a form of flat string that
% passes all \acro{PDF/A} validators.  Furthermore, when Adobe
% Acrobat---at least Adobe Acrobat DC (2019) and earlier
% versions---converts a \acro{PDF} file to \acro{PDF/A} format, it does
% so by discarding all but the first author, which is an unsatisfying
% solution.
%
% Starting with version~4.0, \pkgname{hyperxmp}'s solution is to
% suppress writing metadata to the \acro{PDF} \pdfterm{Info} dictionary
% and write it only to the \acro{XMP} packet.  (\pkgname{hyperxmp}~v5.0+
% is more sophisticated.  It suppresses only the author and keyword
% lists.)  This appears to pacify \acro{PDF/A} validators yet retains
% the author and keyword lists in their non-truncated form.  If desired,
% the \pdfterm{Info} dictionary can be retained by passing the
% \moptname{keeppdfinfo}\label{page:keeppdfinfo} option to
% \cs{hypersetup}.
%
% \usagenote{Acrobat multiline-field bug}
% The \acro{IPTC} Photo Metadata schema states that ``the [contact]
% address is a multiline field''~\cite{IPTC2010:photo-meta}.
% \pkgname{hyperxmp} converts commas in \optname{pdfcontactaddress}'s
% argument to line breaks in the generated \acro{XML}\@.  Unfortunately,
% A bug in Adobe Acrobat---at least in Adobe Acrobat DC (2019) and
% earlier versions---causes that \acro{PDF} reader to discard line
% breaks in the contact address.  Interestingly, Adobe Illustrator CS5
% correctly displays the contact address.  If you find Adobe Acrobat's
% behavior bothersome, you can redefine the
% \DescribeMacro{\xmplinesep}|\xmplinesep| macro as a string to use as
% an address-line separator.  For example, the following replaces all
% commas appearing in \optname{pdfcontactaddress}'s argument with
% semicolons:
%
% \begin{verbatim}
%     \renewcommand*{\xmlinesep}{;}
% \end{verbatim}
%
% \usagenote{Object compression}
% One intention of \acro{XMP} is that metadata embedded in a file be
% readable even without knowledge of the file's format.  That is, the
% metadata are expected to appear as plain text.  Although
% \pkgname{hyperxmp} does its best to honor that intention, it faces
% a few challenges:
%
% \begin{enumerate}
% \item When run with versions of \LuaLaTeX\ earlier than 0.85,
%   \pkgname{hyperxmp} leaves all \acro{PDF} objects uncompressed.  This
%   is due to \LuaLaTeX\ treating object compression as a global
%   parameter, unlike \pdfLaTeX, which treats it as a local parameter.
%   Hence, when \pkgname{hyperxmp} requests that the \acro{XMP} packet
%   be left uncompressed, \LuaLaTeX\ in fact leaves \emph{all}
%   \acro{PDF} streams uncompressed.  Beginning with version~3.0,
%   \pkgname{hyperxmp} includes a workaround that correctly leaves only
%   the \acro{XMP} metadata uncompressed, but this workaround is
%   implemented only for \LuaLaTeX\ v0.85 onwards.
%
% \item \XeLaTeX\ (or, more precisely, the \cmdname{xdvipdfmx} back end)
%   exhibits the opposite problem.  It compresses \emph{all} \acro{PDF}
%   objects, including the ones containing \acro{XMP} metadata.  While
%   Adobe Acrobat can still detect and utilize the \acro{XMP} metadata,
%   non-\acro{PDF}-aware applications are unlikely to see the metadata.
%   Three options to consider are to (1)~use a different program
%   (e.g.,~\LuaLaTeX), (2)~pass the |--output-driver="xdvipdfmx -z0"|
%   option to \XeLaTeX\ to instruct \cmdname{xdvipdfmx} to turn off all
%   compression (which will of course make the \acro{PDF} file
%   substantially larger), or (3)~postprocess the generated \acro{PDF}
%   file by loading it into the commercial version of Adobe Acrobat and
%   re-saving it with the Save As\dots\ menu option.
% \end{enumerate}
%
% \usagenote{Literal commas}
% \label{note:literal-commas}
% \pkgname{hyperxmp} splits the \optname{pdfauthor} and
% \optname{pdfkeywords} lists at commas.  Therefore, when specifying
% \optname{pdfauthor} and \optname{pdfkeywords}, you should separate
% items with commas.  Also, omit ``|and|'' and other text that does not
% belong to any list item.  The following examples should serve as
% clarification:
%
% \begin{description}
%   \item[Wrong:] |pdfauthor={Jack Napier, Edward Nigma,|
%     \textcolor{red}{\texttt{and}} |Harvey Dent}|
%   \item[Wrong:] |pdfauthor={Jack Napier|\textcolor{red}{\texttt{;}}
%     |Edward Nigma|\textcolor{red}{\texttt{;}}
%     |Harvey Dent}|
%   \item[Right:] |pdfauthor={Jack Napier, Edward Nigma, Harvey Dent}|
% \end{description}
%
% \noindent
% \DescribeMacro{\xmpcomma}
% \DescribeMacro{\xmpquote}
% If you need to include a literal comma within an author or keyword
% list (where commas normally separate list items) or a street address
% (where commas normally separate lines), use the |\xmpcomma| macro to
% represent it, and wrap the entire entry containing the comma within
% |\xmpquote{|\dots|}| as shown below:
%
% \begin{verbatim}
%     pdfauthor={\xmpquote{Jack Napier\xmpcomma\ Jr.},
%                \xmpquote{Edward Nigma\xmpcomma\ PhD},
%                \xmpquote{Harvey Dent\xmpcomma\ Esq.}}
%
%     pdfcontactaddress={Office of the President,
%                        \xmpquote{Wayne Enterprises\xmpcomma\ Inc.},
%                        One Wayne Blvd}
% \end{verbatim}
%
% As of version~2.2 of \pkgname{hyperxmp}, it is acceptable to use
% |\xmpcomma| and |\xmpquote| within any \pkgname{hyperxmp} option, not
% just in those in which a comma normally serves as a separator
% (i.e.,~lists and multiline fields).  Outside of cases in which a comma
% serves as a separator, |\xmpcomma| is treated as an ordinary comma,
% and |\xmpquote| returns its argument unmodified.  Hence, it is
% legitimate to use |\xmpcomma| and |\xmpquote| in cases like the
% following
%
% \begin{verbatim}
%     pdfauthortitle={\xmpquote{Psychiatrist\xmpcomma\ Arkham Asylum}}
% \end{verbatim}
%
% \noindent
% (Like most \pkgname{hyperxmp} options, \optname{pdfauthortitle}
% inserts its argument unmodified in an \acro{XMP} tag.)  When in
% doubt, use |\xmpcomma| and |\xmpquote|; it should always be safe
% to do so.
%
% \DescribeMacro{\xmptilde}
% Version~2.4 of \pkgname{hyperxmp} introduces a convenience macro
% called |\xmptilde|.  |\xmptilde| expands to a literal tilde character
% instead of the nonbreaking space that ``|~|'' normally represents.
% Use it to represent \acro{URL}s such as
% \url{http://www.pakin.org/~scott/} (``|http://www.pakin.org/|\linebreak[0]|\xmptilde|
% |scott/|'') in options such as \optname{baseurl},
% \optname{pdfcontacturl} and \optname{pdflicenseurl}.
%
% \usagenote{Unicode support}
% \term{Unicode} support is provided via the \pkgname{hyperref} package.
% If you specify \optname{unicode}|=true| either as a \pkgname{hyperref}
% option or as an argument to the |\hypersetup| command, the document
% can include \term{Unicode} characters in its \acro{XMP} fields.
%
% \usagenote{Automatically specified metadata}
% \pkgname{hyperxmp} attempts to identify certain metadata
% automatically.  The hope is that in many cases, an author can simply
% include |\usepackage{hyperxmp}| in a document's preamble and benefit
% from a modicum of \acro{XMP} metadata with no additional effort.
%
% Currently, \optname{pdftitle} defaults to the document's title as
% specified by |\title{|\dots|}|.  \optname{pdfauthor} defaults to the
% document's author(s) as specified by |\author{|\dots|}|.
% \optname{pdfdate} defaults to the current date and time.
% \optname{pdfmetalang} defaults to the same value as \optname{pdflang}
% if non-empty, ``\xmpterm{x-default}'' otherwise.  \pkgname{hyperxmp}
% recognizes some class-specific metadata as well, such as that provided
% via the \Koma\ letter classes (e.g.,~\clsname{scrlttr2}) and the
% \ACMclass\ article class (\clsname{acmart}).
%
% If a document uses either the \pkgname{babel} or \pkgname{polyglossia}
% packages it is recommended that it \emph{not} explicitly set
% \optname{pdflang}.  \optname{pdflang} accepts only a single language
% name while \pkgname{hyperxmp} can automatically query \pkgname{babel}
% and \pkgname{polyglossia} for a list of all languages used in the
% document and include this list in an \acro{XMP} \xmpprop{dc:language}
% element.
%
% \usagenote{Multilingual metadata}
% \label{note:multilingual}
% The \optname{pdfmetalang} option specifies the language in which the
% document's metadata is written.  It defaults to the value of
% \optname{pdflang}, which specifies the document language.
% \DescribeMacro{\XMPLangAlt} As of version~3.3 of \pkgname{hyperxmp},
% it is possible to include certain metadata---specifically, the
% document's title, subject, and copyright statement---in more than one
% language.  The |\XMPLangAlt| macro provides this functionality.  Usage
% is as follows:
%
% \bigskip
% \indent
% |\XMPLangAlt| \marg{language} |{| \meta{option}|=|\meta{text},~\dots\ |}|
% \bigskip
%
% \noindent
% where \meta{language} is an \acro{ISO} \mbox{639-1} two-letter country
% code with an optional \acro{ISO} \mbox{3166-1} two-letter region code
% (e.g.,~``|en|'' for English or ``|en-US|'' for specifically US
% English); \meta{option} is one of ``|pdftitle|'', ``|pdfsubject|'', or
% ``|pdfcopyright|''; and \meta{text} is the text as expressed in the
% specified language.  By way, of example, the following code provides
% the document title in English then specifies an alternative title to
% use in four other languages:
%
% \begin{verbatim}
%   \hypersetup{%
%     pdfmetalang={en},
%     pdftitle={English title}
%   }
%   \XMPLangAlt{de}{pdftitle={Deutscher Titel}}
%   \XMPLangAlt{fr}{pdftitle={Titre fran\c{c}ais}}
%   \XMPLangAlt{it}{pdftitle={Titolo italiano}}
%   \XMPLangAlt{rm}{pdftitle={Titel rumantsch}}
% \end{verbatim}
%
% \usagenote{Expandable arguments}
% \label{note:expandable}
% All arguments passed to \pkgname{hyperxmp} options must be expandable,
% in \tex\ terminology.  This implies that any macros that are used in
% arguments are limited to a relatively small set of operations (such as
% conditionals and macro expansion) and must produce a string of text.
% Code (such as macro definitions and arithmetic operations) will be
% written to \acro{XMP} as code, not as the result of executing the
% code.
%
% By way of example, the macros provided by the \pkgname{texdate}
% package for typesetting dates are not expandable (at least at the time
% of this writing).  Hence, the |\printfdate{Y}| in the following code
% snippet is not replaced by the current year, as one might expect:
%
% \begin{verbatim}
% \usepackage{texdate}
% \initcurrdate
% \hypersetup{%
%   pdfcopyright={Copyright \textcopyright\ \printfdate{Y}, Scott Pakin}
% }
% \end{verbatim}
%
% \noindent
% Rather, it generates a \xmpprop{dc:rights} tag of the form
% ``\texttt{Copyright \textcopyright\ =2=0=by-1by=0\the\year, Scott
%   Pakin}''.  The garbage in that line corresponds to the remnants of
% the |\printfdate| code after expanding all of the \tex\ primitives and
% certain other control sequences it uses to the empty string.  For
% example, ``|\global\advance\texd@yr| |by-1|'' expands to ``|by-1|''.
%
% It is not possible to determine a~priori whether or not a macro is
% expandable.  The best advice is to carefully inspect the \acro{XMP}
% package in the output file to ensure that any macros used in arguments
% to \pkgname{hyperxmp} options produced the expected output.
%
% \usagenote{Semi-automatic page ranges}
% \label{note:page-counting}
% Although \optname{pdfpagerange} is intended to refer to pages in the
% final, published version of a document, it would be convenient for
% them to be generated automatically when producing a standalone
% \acro{PDF} file that is not intended to be incorporated into a book,
% journal, or other publication (or if it is known that the pages will
% not be renumbered for publication).  One approach is to use the
% \pkgname{totpages} package help generate \optname{pdfpagerange}.  For
% documents numbered from~1 to~$n$, a simple
%
% \Needspace{3\baselineskip}
% \begin{verbatim}
%     \hypersetup{%
%       pdfpagerange={1-\ref*{TotPages}}
%     }
% \end{verbatim}
%
% \noindent
% should suffice.  A bit more effort is needed for documents that change
% numbering schemes, such as using lowercase Roman numerals for the
% front matter and Arabic numerals for the main matter and back matter.
% One approach is to use \cs{label} to mark the first and last page of
% each numbering scheme and specify \optname{pdfpagerange} as in the
% following:
%
% \Needspace{6\baselineskip}
% \begin{verbatim}
%     \hypersetup{%
%       pdfpagerange={%
%         \pageref*{page:begin-front}-\pageref*{page:end-front},%
%         1-\pageref*{TotPages}%
%       }
%     }
% \end{verbatim}
%
% I don't know how unnumbered pages (e.g.,~blank pages and the title
% page) are supposed to be handled.  I suppose blank pages can be
% omitted from \optname{pdfpagerange}, and the title page can be either
% omitted or listed as \texttt{title}, for example.
%
% It appears that at least with version~2.00 of \pkgname{totpages}, the
% |TotPages| label is not defined until after the |\begin{document}|.
% Consequently, using |TotPages| within a \cs{hypersetup} invocation in
% the document's preamble will produce ``|??|'' as the page count in the
% \acro{XMP} packet.  The solution is either to assign
% \optname{pdfpagerange} after the |\begin{document}| or to ask
% \LaTeX\ to do that on your behalf:
%
% \begin{verbatim}
%     \AtBeginDocument{%
%       \hypersetup{%
%         pdfpagerange={1-\ref*{TotPages}}
%       }%
%     }
% \end{verbatim}
%
% \usagenote{Automatic computation of the PDF byte count}
% \label{note:auto-byte-count}
%
% The \schema[PRISM Basic Metadata]{\protect\acro{PRISM} Basic Metadata}
% schema~\cite{PRISM2012:basic-meta} defines a \xmpprop{prism:byteCount}
% property that indicates the \acro{PDF} file size in bytes.
% \pkgname{hyperxmp} computes this value automatically when the document
% is built using \LuaLaTeX\ but not when using any other \TeX\ engine.
% Note that \pkgname{hyperxmp} uses the file size from the
% \emph{previous} run of \LuaLaTeX\ because the new \acro{PDF} file is
% not yet complete.  Consequently, one extra compilation is needed for
% the byte count to converge relative to the the number of compilations
% that would otherwise be required.
%
% Starting with \pkgname{hyperxmp}~v5.9, the \pkgname{hyperxmp}
% distribution includes a Perl\index{Perl} script called
% \progname{hyperxmp-add-bytecount} that edits a \acro{PDF} file in
% place, adding or replacing the \xmpprop{prism:byteCount} property with
% one that specifies the final file size.\footnote{The script was in
%   fact introduced with \progname{hyperxmp}~v5.8 and was then called
%   \texttt{add\_byteCount}.}  Run the script as
% ``\progname{hyperxmp-add-bytecount} \meta{filename.pdf}''.
%
% The \progname{latexmk} build tool can be configured to run
% \progname{hyperxmp-add-bytecount} automatically every time a \acro{PDF} file
% is generated.  Simply add the code shown in Figure~\ref{fig:latexmkrc}
% to your \progname{latexmk} configuration file.  See
% \href{http://mirrors.ctan.org/support/latexmk/latexmk.pdf}{the
%   \progname{latexmk} manual} for information on configuration-file
% naming on different operating systems and explanations of the hook
% functions used in Figure~\ref{fig:latexmkrc}.
%
% \changes{v5.8}{2020/11/18}{Distribute an
%   \protect\progname{add\_byteCount} script and document some sample
%   \protect\progname{latexmk} configuration code that invokes it.
%   Thanks to John Collins for providing both of those}
% \changes{v5.9}{2020/11/22}{At Karl Berry's request, rename
%   \protect\progname{add\_byteCount} to the less generic-sounding
%   \protect\progname{hyperxmp-add-bytecount}}
%
% \iffalse
%<*listings>
% \fi
\newsavebox{\latexmkrcbox}
\begin{lrbox}{\latexmkrcbox}
  \begin{lstlisting}[
      language=perl,
      columns=fullflexible,
      linewidth=19pc,
      frame=single,
      basicstyle=\footnotesize,
      showstringspaces=false,
      upquote=true,
      literate={-}{-}{1}
    ]
foreach my $cmd ( "latex", "lualatex", "pdflatex", "xelatex",
                  "dvipdf", "xdvipdfmx", "ps2pdf" ) {
    ${$cmd} = "internal mycmd ${$cmd}";
}

sub mycmd {
    my $retval = system @_;
    if ( $$Pdest =~ /\.pdf$/ ) {
        system 'hyperxmp-add-bytecount', $$Pdest;
    }
    return $retval;
}
  \end{lstlisting}
\end{lrbox}
% \iffalse
%</listings>
% \fi
%
% \begin{figure}
%   \centering
%   \usebox{\latexmkrcbox}
%   \caption{ \progname{latexmk} configuration-file code for
%     automatically invoking \progname{hyperxmp-add-bytecount} every time a
%     \acro{PDF} file is generated}
%   \label{fig:latexmkrc}
% \end{figure}
%
% Even though \pkgname{hyperxmp} can compute the byte count
% automatically when run from \LuaLaTeX, users of \progname{latexmk}
% need to use configuration-file code like that shown in
% Figure~\ref{fig:latexmkrc}.  Otherwise, \progname{latexmk} would
% compile the document one time too few for the byte count to
% converge. It is recommended that those who use both \progname{latexmk}
% and \pkgname{hyperxmp} configure \progname{latexmk} to be
% \pkgname{hyperxmp}-aware.
%
%
% \StopEventually{^^A
% \section{Help Wanted}
%
% \paragraph{Comma handling}
% Ideally, \texttt{\string\xmpquote} should automatically replace all
% commas with \texttt{\string\xmpcomma}.  Unfortunately, my \tex\ skills
% are insufficient to pull that off.  If you know a way to make
% \texttt{\string\xmpquote\string{Hello, world\string}} work with both
% \term{Unicode} and non-\term{Unicode} encodings and with all
% \tex\ engines (\pdfTeX, \LuaTeX, \XeTeX, etc.), please send me a code
% patch.
%
% \appendix
%
% \section{Sample XMP Packet}
% \label{sec:sample-packet}
%
% The following is an example of a complete \acro{XMP} packet as may be
% produced by \pkgname{hyperxmp}.  This packet corresponds to the
% metadata included in the sample \LaTeX\ document presented
% \vpagerefrange{page:begin-sample-doc}{page:end-sample-doc}.  For
% clarity, metadata values, either specified explicitly by the document
% or introduced automatically by \pkgname{hyperxmp}, are colored blue.
%
% \input{einstein-xmp}
%
% \begin{thebibliography}{99}
% \bibitem{NISO2008:jav}
% Beverley Acreman, Claire Bird, Catherine Jones, Peter McCracken, Cliff Morgan,
%   John Ober, Evan Owens, T.~Scott Plutchak, Bernie Rous, and Andrew Wray.
% \newblock {J}ournal {A}rticle {V}ersions ({JAV}): Recommendations of the
%   {NISO}/{ALPSP} {JAV} {T}echnical {W}orking {G}roup.
% \newblock Recommended practice, National Information Standards Organization,
%   Baltimore, Maryland, USA, April 2008.
% \newblock ISBN~\mbox{978-1-880124-79-6}.
% \newblock Available from
%   \url{https://www.niso.org/sites/default/files/2017-08/RP-8-2008.pdf}.
%
% \bibitem{Adobe2010:pdfmark}
% Adobe Systems, Inc., San Jose, California.
% \newblock \emph{{A}dobe {A}crobat~{X} {SDK} Help, pdfmark Reference}.
% \newblock Available from
%   \url{http://www.adobe.com/devnet/acrobat/documentation.html}.
%
% \bibitem{Adobe1996:postscript}
% {Adobe Systems, Inc.}
% \newblock \emph{{P}ost{S}cript Language Reference Manual}.
% \newblock Addison-Wesley, 2nd edition, January 1996, ISBN: \mbox{0-201-18127-4}.
%
% \bibitem{Adobe2008:PDF}
% Adobe Systems, Inc., San Jose, California.
% \newblock \emph{Document Management---Portable Document Format---Part 1:
%   PDF~1.7}, July 2008.
% \newblock ISO \mbox{32000-1} standard document. Available from
%   \url{http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf}.
%
% \bibitem{Adobe2012:XMP}
% Adobe Systems, Inc., San Jose, California.
% \newblock \emph{{XMP} Specification Part~1: Data model, Serialization, and Core
%   Properties}, April 2012.
% \newblock Available from
%   \url{http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/cc-201306/XMPSpecificationPart1.pdf}.
%
% \bibitem{DCMI2012:meta-terms}
% DCMI Usage Board
% \newblock \emph{DCMI Metadata Terms}, June~14, 2012.
% \newblock Available from \url{http://dublincore.org/documents/dcmi-terms/}.
%
% \bibitem{Downes1994:ATB15}
% Michael Downes.
% \newblock Around the bend~\#15, answers, 4th (last) installment.
% \newblock \href{news:comp.text.tex}{\texttt{comp.text.tex}} newsgroup posting,
%   January~3, 1994.
% \newblock Archived by Google at
%   \url{http://groups.google.com/group/comp.text.tex/msg/7da7643b9e8f3b48}.
%
% \bibitem{PRISM2012:basic-meta}
% International Digital Enterprise Alliance, Inc.
% \newblock \emph{Publishing Requirements for Industry Standard Metadata,
%   Version~3.0: {PRISM} Basic Metadata Specification}, October~12, 2012.
% \newblock Available from
%   \url{http://www.prismstandard.org/specifications/3.0/PRISM_Basic_Metadata_3.0.htm}.
%
% \bibitem{PRISM2012:cont-voc}
% International Digital Enterprise Alliance, Inc.
% \newblock \emph{Publishing Requirements for Industry Standard Metadata,
%   Version~3.0: {PRISM} Controlled Vocabularies Specification}, October~4, 2012.
% \newblock Available from
%   \url{http://www.prismstandard.org/specifications/3.0/PRISM_CV_Spec_3.0.pdf}.
%
% \bibitem{IPTC2010:photo-meta}
% International Press Telecommunications Council.
% \newblock \emph{{IPTC} Photo Metadata: Core 1.1/Extension 1.1}, July 2010.
% \newblock Revision~1. Available from
%   \url{http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata-201007_1.pdf}.
%
% \bibitem{IANA2011:lang-tags}
% {Internet Assigned Numbers Authority}.
% \newblock Language subtag registry, January~11, 2011.
% \newblock Available from
%   \url{http://www.iana.org/assignments/language-subtag-registry}.
%
% \bibitem{Leach2005:uuid}
% Paul~J. Leach, Michael Mealling, and Rich Salz.
% \newblock A {U}niversally {U}nique {ID}entifier ({UUID}) {URN} namespace.
% \newblock Request for Comments 4122, Internet Engineering Task Force, Network
%   Working Group, July 2005.
% \newblock Category: Standards Track. Available from
%   \url{http://www.ietf.org/rfc/rfc4122.txt}.
%
% \bibitem{PDFA2008:xmp-props}
% PDF/A Competence Center, Berlin, Germany.
% \newblock \emph{{T}ech{N}ote~0008: Predefined {XMP} Properties in {PDF/A-1}},
%   March~20, 2008.
% \newblock Available from
%   \url{http://www.pdfa.org/wp-content/uploads/2011/08/tn0008_predefined_xmp_properties_in_pdfa-1_2008-03-20.pdf}.
%
% \bibitem{PDFA2008:ext-schemas}
% PDF/A Competence Center, Berlin, Germany.
% \newblock \emph{{T}ech{N}ote~0009: {XMP} Extension Schemas in {PDF/A-1}},
%   March~20, 2008.
% \newblock Available from
%   \url{http://www.pdfa.org/wp-content/uploads/2011/08/tn0009_xmp_extension_schemas_in_pdfa-1_2008-03-20.pdf}.
%
% \bibitem{Wolf1997:date-time}
% Misha Wolf and Charles Wicksteed.
% \newblock Date and time formats.
% \newblock Note NOTE-datetime, World Wide Web Consortium (W3C), September~15,
%   1997.
% \newblock Available from \url{http://www.w3.org/TR/NOTE-datetime}.
% \end{thebibliography}
% }
%
%
% \section{Implementation}
%
% This section presents the commented \LaTeX\ source code for
% \pkgname{hyperxmp}.  Read this section only if you want to learn how
% \pkgname{hyperxmp} is implemented.
%
% \bigskip
%
% One thing to bear in mind when reading the \pkgname{hyperxmp} source
% code is that different actions occur at different times throughout
% document processing:
%
% \begin{enumerate}
%   \item |\usepackage{hyperxmp}|: \pkgname{hyperxmp} parses package
%     options, defines a number of commands, loads various helper
%     packages, and assigns default values to most \acro{XMP} fields.
%
%   \item |\begin{document}|: \pkgname{hyperxmp} loads certain packages
%     such as \pkgname{hyperref} and \pkgname{ifdraft} and queries
%     natural-language information from \pkgname{babel} and
%     \pkgname{polyglossia} that becomes available only at the end of
%     the preamble.
%
%   \item |\end{document}|: \pkgname{hyperxmp} finalizes certain data
%     that are known only at the end of the document, such as the page
%     count, and writes the \acro{XMP} packet to the \acro{PDF} file.
% \end{enumerate}
%
% \iffalse
%<*package>
% \fi
%
% \subsection{Initial preparation}
% \label{sec:initial-prep}
%
% \changes{v5.11}{2022/10/02}{Disable \protect\pkgname{hyperxmp} if
%    \LaTeX3 document metadata is available.  Document metadata implies
%    the presence of PDF management, which completely breaks
%    \protect\pkgname{hyperxmp}}
%    \begin{macrocode}
\IfDocumentMetadataTF{%
  \PackageWarning
      {hyperxmp}
      {Disabling hyperxmp because it is incompatible with PDF management}
}{}
\IfDocumentMetadataTF{\endinput}{}
%    \end{macrocode}
%
% \changes{v1.2}{2011/04/17}{Made the package compatible with \pkgname{ngerman}.
%   Thanks to Tobias Mueller for the bug report.}
%
% \begin{macro}{\hyxmp@dq@code}
% The \pkgname{ngerman} package redefines
% ``\,{\fontencoding{T1}\selectfont\textquotedbl}\,'' as an active
% character, which causes problems for \pkgname{hyperxmp} when it tries
% to use that character.  We therefore save the double-quote character's
% current category code in |\hyxmp@dq@code| and mark the character as
% category code~12 (``other'').  The original category code is restored
% at the end of the package code (Section~\ref{sec:clean-up}).
%    \begin{macrocode}
\edef\hyxmp@dq@code{\the\catcode`\"}
\catcode`\"=12
%    \end{macrocode}
% \end{macro}
%
% \changes{v1.5}{2012/03/10}{Made the \protect\acro{XMP} inclusion more robust.
%   Thanks to Heiko Oberdiek for the bug report and suggested modifications.}
%
% \begin{macro}{\hyxmp@at@end}
% The |\hyxmp@at@end| macro includes code at the end of the document.
% When available (as is the case in most modern \tex\ backends),
% \cs{AtEndDocument} works well enough.  Otherwise, we invoke
% \cs{AtEndDvi} from the \pkgname{atenddvi} package, which is robust but
% requires an addition \LaTeX\ run.
% \changes{v5.3}{2020/05/29}{Use \protect\cs{AtEndDocument} in all
%   \protect\tex\ back ends that provide it.  Thanks to Nelson Posse
%   Lago for pointing out why \protect\pkgname{atenddvi} is best avoided
%   if possible}
% \changes{v5.11}{2022/10/16}{Use \protect\cs{AddToHook} when available.
%   This addresses a bug reported on \protect\TeX\ StackExchange by joHub
%   and solved by Ulrike Fischer}
%    \begin{macrocode}
\@ifundefined{AddToHook}{%
  \@ifundefined{AtEndDocument}{%
    \RequirePackage{atenddvi}
    \let\hyxmp@at@end=\AtEndDvi
  }{%
    \let\hyxmp@at@end=\AtEndDocument
  }
}{%
  \def\hyxmp@at@end{\AddToHook{shipout/lastpage}}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@jobname}
% Given an expanded \cs{jobname} followed by \cs{relax}, invoke the
% \cs{hyxmp@set@jobname@dbl} macro if the job name is surrounded by
% double quotes and the \cs{hyxmp@set@jobname@plain} macro otherwise.
%    \begin{macrocode}
\def\hyxmp@set@jobname#1\relax{%
  \@ifnextchar"{\hyxmp@set@jobname@dbl}{\hyxmp@set@jobname@plain}#1\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@jobname@dbl}
% \begin{macro}{\hyxmp@jobname}
% Set \cs{hyxmp@jobname} to to |#1|, discarding the surrounding double
% quotes.
%    \begin{macrocode}
\def\hyxmp@set@jobname@dbl"#1"\relax{\xdef\hyxmp@jobname{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@jobname@plain}
% \begin{macro}{\hyxmp@jobname}
% Set \cs{hyxmp@jobname} to to |#1|.
%    \begin{macrocode}
\def\hyxmp@set@jobname@plain#1\relax{\xdef\hyxmp@jobname{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% Define \cs{hyxmp@jobname} as a sanitized version of \cs{jobname}.  The
% problem with using \cs{jobname} directly is that it surrounds the
% filename with double quotes if it contains a space character.  For
% example, a source file named \texttt{my-file.tex} results in a
% \cs{jobname} of ``\texttt{my-file}'', but a source file named
% \texttt{my file.tex} results in a \cs{jobname} of ``|"my file"|''.
% Trying to access |"my file".log| (as is done on
% page~\pageref{page:jobname-log}) will fail because the filename does
% not in fact contain literal double quotes.
% \changes{v5.5}{2020/07/28}{Correctly handle source files with spaces
%   in their name.  Thanks to Peter Dyballa for the bug report}
%    \begin{macrocode}
\expandafter\hyxmp@set@jobname\jobname\relax
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@aep@toks}
% In order for \pkgname{hyperxmp} to be loaded safely during
% \cs{AtEndPreamble} we need to ensure that we perform no
% \cs{AtEndPreamble} actions until all top-level macro definitions have
% been made.  The most straightforward approach would be to move all of
% \pkgname{hyperxmp}'s \cs{AtEndPreamble} stanzas to the end of the
% package.  However, this degrades readability of the source code.  For
% instance, an \cs{AtEndPreamble} stanza related to integration with
% \pkgname{hyperref} could no longer appear in the ``Integration with
% \pkgname{hyperref}'' section (Section~\ref{sec:hyperref-int}).  Hence,
% we instead store in a token list, \cs{hyxmp@aep@toks}, each
% \cs{AtEndPreamble} stanza as we encounter it.  This token list is
% evaluated as one of the package's final actions
% (Section~\ref{sec:clean-up}).
%    \begin{macrocode}
\newtoks{\hyxmp@aep@toks}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Integration with \textsf{hyperref}}
% \label{sec:hyperref-int}
%
% An important design decision underlying \pkgname{hyperxmp} is that the
% package should integrate seamlessly with \pkgname{hyperref}.  To that
% end, \pkgname{hyperxmp} takes \acro{XMP} metadata from
% \pkgname{hyperref}'s \optname{baseurl}, \optname{pdfauthor},
% \optname{pdfkeywords}, \optname{pdflang}, \optname{pdfproducer},
% \optname{pdfsubject}, \optname{pdftrapped}, and \optname{pdftitle}
% options.  It also introduces a number of new options, which are listed
% \vpagerefrange[above]{page:begin-new-options}{page:end-new-options}.
% For consistency with \pkgname{hyperref}'s document-metadata naming
% conventions (which are in turn based on \LaTeX's document-metadata
% naming conventions), we do not prefix metadata-related macro names
% with our package-specific |\hyxmp@| prefix.  That is, we use names
% like |\@pdfcopyright| instead of |\hyxmp@pdfcopyright|.
%
% \bigskip
%
% We load a bunch of helper packages: \pkgname{kvoptions} for
% package-option processing, \pkgname{pdfescape} and \pkgname{stringenc}
% for re-encoding \term{Unicode} strings, \pkgname{intcalc} for
% performing integer calculations (division and modulo), \pkgname{iftex}
% for determining which \tex\ engine is being used, \pkgname{ifmtarg}
% for testing if a macro argument is empty or all spaces,
% \pkgname{etoolbox} for dynamically patching existing commands
% (specifically, \pkgname{hyperref}'s |\PDF@FinishDoc|), and
% \pkgname{ifthen} for convenient string comparisons.
%    \begin{macrocode}
\RequirePackage{kvoptions}
\RequirePackage{pdfescape}
\RequirePackage{stringenc}
\RequirePackage{intcalc}
\RequirePackage{iftex}
\RequirePackage{ifmtarg}
\RequirePackage{etoolbox}
\RequirePackage{ifthen}
%    \end{macrocode}
%
% There are a few places where \pkgname{hyperxmp} can take advantage of
% \LuaTeX\ features.  To simplify the use of \LuaTeX\ we load the
% \pkgname{luacode} package.
%    \begin{macrocode}
\ifLuaTeX
  \RequirePackage{luacode}
\fi
%    \end{macrocode}
%
% \begin{macro}{\@ifmtargexp}
% \begin{macro}{\@ifnotmtargexp}
% |\@ifmtarg| and |\@ifnotmtarg| do not expand their first argument.
% Define |\@ifmtargexp| and |\@ifnotmtargexp| as expanding versions of
% those macros.
%    \begin{macrocode}
\def\@ifmtargexp#1{\expandafter\@ifmtarg\expandafter{#1}}
\def\@ifnotmtargexp#1{\expandafter\@ifnotmtarg\expandafter{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@if@def@and@nonempty}
% This macro combines \cs{@ifundefined} and \cs{@ifmtargexp}.  If the
% macro named |#1| is both defined and non-empty, evaluate~|#2|.
% Otherwise, evaluate~|#3|.
% \changes{v5.3}{2020/06/07}{Added this macro}
%    \begin{macrocode}
\newcommand*{\@if@def@and@nonempty}[3]{%
  \@ifundefined{#1}{#3}{%
    \expandafter\@ifmtargexp\expandafter{\csname#1\endcsname}{#3}{#2}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfstringdef}
% \begin{macro}{\hyxmp@textunderscore}
% Because \pkgname{hyperxmp} uses underscores to represent hard spaces,
% we need ``|\_|'' to map initially to something other than an
% underscore, in particular the \acro{ASCII} \acro{NAK}~(|^^U|)
% character.  To accomplish this, we wrap \pkgname{hyperref}'s
% |\pdfstringdef| macro with our own version that temporarily does the
% proper substitution.  Later in the execution, after underscores have
% been replaced with spaces, we replace \acro{NAK} characters with
% underscores.
% \changes{v2.5}{2014/06/19}{Added this macro}
%    \begin{macrocode}
\newcommand{\hyxmp@pdfstringdef}[2]{%
  \let\hyxmp@textunderscore=\textunderscore
  \let\textunderscore=\hyxmp@uscore
  \pdfstringdef{#1}{#2}%
  \let\textunderscore=\hyxmp@textunderscore
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfdatetime}
% Prepare to store the document's date and (optionally) time.  Whether
% specified by the author in \acro{XMP} format or \acro{PDF} format
% (see Section~\ref{sec:date-manip}) we always store |\@pdfdatetime| as
% an \acro{XMP}-format string.
%    \begin{macrocode}
\def\@pdfdatetime{}
\define@key{Hyp}{pdfdate}{%
  \begingroup
    \Hy@unicodefalse
%    \end{macrocode}
% \begin{macro}{\next}
% Expand \optname{pdfdate}'s argument and convert it to \acro{XMP} format.
%    \begin{macrocode}
    \edef\next{%
      \noexpand\hyxmp@pdfstringdef\noexpand\@pdfdatetime{%
        \noexpand\hyxmp@as@xmp@date{#1}}%
    }%
    \next
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfmetadatetime}
% Prepare to store the document's metadata date and (optionally) time.
% Whether specified by the author in \acro{XMP} format or \acro{PDF}
% format (see Section~\ref{sec:date-manip}) we always store
% |\@pdfmetadatetime| as an \acro{XMP}-format string.
%    \begin{macrocode}
\def\@pdfmetadatetime{}
\define@key{Hyp}{pdfmetadate}{%
  \begingroup
    \Hy@unicodefalse
%    \end{macrocode}
% \begin{macro}{\next}
% Expand \optname{pdfmetadate}'s argument and convert it to \acro{XMP} format.
%    \begin{macrocode}
    \edef\next{%
      \noexpand\hyxmp@pdfstringdef\noexpand\@pdfmetadatetime{%
        \noexpand\hyxmp@as@xmp@date{#1}}%
    }%
    \next
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfcopyright}
% Prepare to store the document's copyright statement.
%    \begin{macrocode}
\def\@pdfcopyright{}
\define@key{Hyp}{pdfcopyright}{\hyxmp@pdfstringdef\@pdfcopyright{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdftype}
% Prepare to store the document's logical type, which defaults to ``|Text|''.
%    \begin{macrocode}
\def\@pdftype{Text}
\define@key{Hyp}{pdftype}{\hyxmp@pdfstringdef\@pdftype{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdflicenseurl}
% Prepare to store the \acro{URL} containing the document's license
% agreement.
%    \begin{macrocode}
\def\@pdflicenseurl{}
\define@key{Hyp}{pdflicenseurl}{\hyxmp@pdfstringdef\@pdflicenseurl{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfauthortitle}
% Prepare to store the author's position/title (e.g.,~Staff Writer).
%    \begin{macrocode}
\def\@pdfauthortitle{}
\define@key{Hyp}{pdfauthortitle}{\hyxmp@pdfstringdef\@pdfauthortitle{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcaptionwriter}
% Prepare to store the name of the person who inserted the
% \pkgname{hyperxmp} metadata.
%    \begin{macrocode}
\def\@pdfcaptionwriter{}
\define@key{Hyp}{pdfcaptionwriter}{\hyxmp@pdfstringdef\@pdfcaptionwriter{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfmetalang}
% Prepare to store the natural language of the document's metadata,
% typically as an \acro{ISO}~\mbox{639-1} two-letter abbreviation.
%    \begin{macrocode}
\def\@pdfmetalang{}
\define@key{Hyp}{pdfmetalang}{\hyxmp@pdfstringdef\@pdfmetalang{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@no@bad@parts}
% Complain about a bad \optname{pdfapart} or \optname{pdfuapart} if given
% trailing non-digits after a part number.
%    \begin{macrocode}
\def\hyxmp@no@bad@parts#1\relax{%
  \@ifnotmtarg{#1}{%
    \PackageWarning{hyperxmp}{pdfapart and pdfuapart must be numeric}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@hyxmp@count}
% \changes{v5.11}{2022/10/02}{Added this macro to fix a bug with
%   \protect\optname{pdfapart}.  Thanks to John H. Lienhard and
%   Kartik Singhal for their bug reports}
% Define a temporary counter.  The code previously used \cs{@tempcnta},
% but this is no longer safe within \cs{pdfstringdef} as of more recent
% versions of \pkgname{hyperref}.
%    \begin{macrocode}
\newcount\@hyxmp@count
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfapart}
% Prepare to store the \acro{PDF/A} part ID, which defaults to~``1''
% if \optname{pdfa} is passed to \pkgname{hyperref}.
%    \begin{macrocode}
\def\@pdfapart{}
\define@key{Hyp}{pdfapart}{%
  \afterassignment\hyxmp@no@bad@parts\@hyxmp@count=0#1\relax
  \hyxmp@pdfstringdef\@pdfapart{\the\@hyxmp@count}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfaconformance}
% Prepare to store the \acro{PDF/A} conformance ID, which defaults to~``b''
% if \optname{pdfa} is passed to \pkgname{hyperref} and |\@pdfapart| is
% empty.
%    \begin{macrocode}
\def\@pdfaconformance{}
\define@key{Hyp}{pdfaconformance}{%
  \uppercase{\hyxmp@pdfstringdef\@pdfaconformance{#1}}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfuapart}
% Prepare to store the \acro{PDF/UA} part ID.
%    \begin{macrocode}
\def\@pdfuapart{}
\define@key{Hyp}{pdfuapart}{%
  \afterassignment\hyxmp@no@bad@parts\@hyxmp@count=0#1\relax
  \hyxmp@pdfstringdef\@pdfuapart{\the\@hyxmp@count}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@pdfx@major}
% Parse \optname{pdfxstandard} as ``|PDF/X-|\meta{major}\meta{other}'',
% setting |\hyxmp@pdfx@major| to \meta{major}.
%    \begin{macrocode}
\newcommand*{\hyxmp@set@pdfx@major}[1]{\hyxmp@set@pdfx@major@i#1!}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@pdfx@major@i}
% This is the first helper macro for |\hyxmp@set@pdfx@major|.  It stores
% the \acro{PDF/X} major version in |\@hyxmp@count|.
%    \begin{macrocode}
\def\hyxmp@set@pdfx@major@i PDF/X-{%
  \afterassignment\hyxmp@set@pdfx@major@ii
  \@hyxmp@count=%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@pdfx@major@ii}
% \begin{macro}{\hyxmp@pdfx@major}
% This is the second helper macro for |\hyxmp@set@pdfx@major|.  It
% copies the \acro{PDF/X} major version from |\@hyxmp@count| to
% |\@hyxmp@pdfx@major| and discards the rest of the \acro{PDF/X}
% standard string.
%    \begin{macrocode}
\def\hyxmp@set@pdfx@major@ii#1!{%
  \edef\hyxmp@pdfx@major{\the\@hyxmp@count}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@check@std}
% \changes{v5.0}{2020/03/10}{Added this macro}
% Compare a user-provided string to a fixed string.  (Assumption: Both
% are names of \acro{PDF/X} standard versions.)  If they match, undefine
% |\next|, which we assume was previously defined to issue an
% ``unrecognized standard'' warning message.
%    \begin{macrocode}
\newcommand*\hyxmp@check@std[2]{%
  \ifthenelse{\equal{#1}{#2}}%
             {\global\let\next=\relax}%
             {}%
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfxstandard}
% Prepare to store the \acro{PDF/X} standard.
% \changes{v5.0}{2020/03/10}{Added this macro}
%    \begin{macrocode}
\def\@pdfxstandard{}
\def\hyxmp@pdfx@major{}
\define@key{Hyp}{pdfxstandard}{%
  \hyxmp@pdfstringdef\@pdfxstandard{#1}%
%    \end{macrocode}
% \begin{macro}{\next}
% Issue a warning message if the \acro{PDF/X} standard named by the user
% does not appear in a list of known \acro{PDF/X} standards.  This is to
% caution the user that \pkgname{hyperxmp} generates standard-specific
% \acro{XMP} metadata and it can only guess at the correct format for
% new standard versions.  (See the comments on
% page~\pageref{page:pdfx-id-schema} above the definition of
% |\hyxmp@pdfx@id@schema|, for example.)
%    \begin{macrocode}
  \gdef\next{%
    \PackageWarning{hyperxmp}{Unrecognized PDF/X standard `#1'}%
  }%
  \hyxmp@check@std{#1}{PDF/X-1a:2001}%
  \hyxmp@check@std{#1}{PDF/X-1a:2003}%
  \hyxmp@check@std{#1}{PDF/X-3:2002}%
  \hyxmp@check@std{#1}{PDF/X-3:2003}%
  \hyxmp@check@std{#1}{PDF/X-4}%
  \hyxmp@check@std{#1}{PDF/X-4p}%
  \hyxmp@check@std{#1}{PDF/X-5g}%
  \hyxmp@check@std{#1}{PDF/X-5n}%
  \hyxmp@check@std{#1}{PDF/X-5pg}%
  \next
%    \end{macrocode}
% \begin{macro}{\hyxmp@pdfx@major}
% Parse the \acro{PDF/X} major version number from
% \optname{pdfxstandard} and assign it to |\hyxmp@pdfx@major|.
%    \begin{macrocode}
  \hyxmp@set@pdfx@major{#1}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfsource}
% Prepare to store the document's source, which defaults to the value of
% |\jobname|.
% \changes{v3.3}{2017/07/16}{Added this macro and the corresponding
%   \protect\optname{pdfsource} option, at Niklas Beisert's request}
%    \begin{macrocode}
\edef\@pdfsource{\hyxmp@jobname.tex}
\define@key{Hyp}{pdfsource}{\hyxmp@pdfstringdef\@pdfsource{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@DocumentID}
% Prepare to store a \acro{UUID} that represents the document.
% \changes{v3.5}{2018/11/27}{Added the \protect\optname{pdfdocumentid}
%   option, at Michael Osipov's request}
%    \begin{macrocode}
\def\hyxmp@DocumentID{}
\define@key{Hyp}{pdfdocumentid}{\hyxmp@pdfstringdef\hyxmp@DocumentID{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@InstanceID}
% Prepare to store a \acro{UUID} that represents the current instance of
% the document.
% \changes{v3.5}{2018/11/27}{Added the \protect\optname{pdfinstanceid}
%   option, at Michael Osipov's request}
%    \begin{macrocode}
\def\hyxmp@InstanceID{}
\define@key{Hyp}{pdfinstanceid}{\hyxmp@pdfstringdef\hyxmp@InstanceID{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfversionid}
% Prepare to store a string that represents the current version of
% the document.  It defaults to ``|1|''.
%    \begin{macrocode}
\def\@pdfversionid{1}
\define@key{Hyp}{pdfversionid}{\hyxmp@pdfstringdef\@pdfversionid{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifdraft}
% \begin{macro}{\next}
% Use the \pkgname{ifdraft} package to determine if this is a draft or
% final document.  The challenge here is that we want to use
% \pkgname{ifdraft} if it's already loaded, load it if not, and not
% break any incompatible, author-defined \cs{ifdraft} macros that may
% occur either before or after the |\usepackage{hyperxmp}|.  Our
% solution begins by defining a new group.  Then, if \pkgname{ifdraft}
% is not yet loaded, we locally undefine \cs{ifdraft} and load the
% package.  In this case, we later ``unload'' the package by setting
% \cs{ver@ifdraft.sty} to \cs{relax}.
% \changes{v5.2}{2020/04/18}{Define \protect\cs{ifdraft} only locally, at
%   Niklas Beisert's request}
%    \begin{macrocode}
\begingroup
  \@ifpackageloaded{ifdraft}{%
    \let\next=\relax
  }{%
    \let\ifdraft=\relax
    \RequirePackage{ifdraft}%
    \def\next{%
      \expandafter\global\expandafter\let\csname ver@ifdraft.sty\endcsname=\relax
    }%
  }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfrendition}
% \changes{v5.0}{2020/02/27}{Added the \protect\optname{pdfrendition}
%   option}
% Prepare to store a tag describing how this rendition of the document
% differs from the master.  The default value is |default|, which
% indicates the master document, except in the case of
% |\documentclass[draft]|, for which |\@pdfrendition| defaults to
% |draft|.
%    \begin{macrocode}
  \ifdraft{%
    \gdef\@pdfrendition{draft}%
  }{%
    \gdef\@pdfrendition{default}%
  }
  \next
\endgroup
\define@key{Hyp}{pdfrendition}{\hyxmp@pdfstringdef\@pdfrendition{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfpublication}
% Prepare to store the name of the publication in which the
% document was published.
%    \begin{macrocode}
\def\@pdfpublication{}
\define@key{Hyp}{pdfpublication}{\hyxmp@pdfstringdef\@pdfpublication{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfpubtype}
% Prepare to store the type of the publication in which the
% document was published.
%    \begin{macrocode}
\def\@pdfpubtype{}
\define@key{Hyp}{pdfpubtype}{\hyxmp@pdfstringdef\@pdfpubtype{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfbytes}
% Prepare to store the size of the file in bytes.
%    \begin{macrocode}
\def\@pdfbytes{}
\define@key{Hyp}{pdfbytes}{\hyxmp@pdfstringdef\@pdfbytes{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfnumpages}
% Prepare to store the number of pages in the file.
%    \begin{macrocode}
\def\@pdfnumpages{}
\define@key{Hyp}{pdfnumpages}{\hyxmp@pdfstringdef\@pdfnumpages{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfissn}
% Prepare to store the \acro{ISSN} of the publication in which the
% document was published.
%    \begin{macrocode}
\def\@pdfissn{}
\define@key{Hyp}{pdfissn}{\hyxmp@pdfstringdef\@pdfissn{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfeissn}
% Prepare to store the \acro{ISSN} of the electronic version of the
% publication in which the document was published.
%    \begin{macrocode}
\def\@pdfeissn{}
\define@key{Hyp}{pdfeissn}{\hyxmp@pdfstringdef\@pdfeissn{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfisbn}
% Prepare to store the \acro{ISBN} of the publication in which the
% document was published.
%    \begin{macrocode}
\def\@pdfisbn{}
\define@key{Hyp}{pdfisbn}{\hyxmp@pdfstringdef\@pdfisbn{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfbookedition}
% Prepare to store the edition of the book in which the document
% was published.
%    \begin{macrocode}
\def\@pdfbookedition{}
\define@key{Hyp}{pdfbookedition}{\hyxmp@pdfstringdef\@pdfbookedition{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfpublisher}
% Prepare to store the name of the document's publisher.
%    \begin{macrocode}
\def\@pdfpublisher{}
\define@key{Hyp}{pdfpublisher}{\hyxmp@pdfstringdef\@pdfpublisher{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfvolumenum}
% Prepare to store the volume identifier of the publication in which the
% document was published.
%    \begin{macrocode}
\def\@pdfvolumenum{}
\define@key{Hyp}{pdfvolumenum}{\hyxmp@pdfstringdef\@pdfvolumenum{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfissuenum}
% Prepare to store the identifier of the issue within a volume of the
% publication in which the document was published.
%    \begin{macrocode}
\def\@pdfissuenum{}
\define@key{Hyp}{pdfissuenum}{\hyxmp@pdfstringdef\@pdfissuenum{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfpagerange}
% Prepare to store the document's range of pages within the publication
% in which the document was published.
%    \begin{macrocode}
\def\@pdfpagerange{}
\define@key{Hyp}{pdfpagerange}{\hyxmp@pdfstringdef\@pdfpagerange{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfdoi}
% Prepare to store a \acro{DOI} that represents the current instance of
% the document.
%    \begin{macrocode}
\def\@pdfdoi{}
\define@key{Hyp}{pdfdoi}{\hyxmp@pdfstringdef\@pdfdoi{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfurl}
% Prepare to store a \acro{URL} that represents where the document
% can be found.  Note that we do not prepend \optname{baseurl} to
% the value provided.
%    \begin{macrocode}
\def\@pdfurl{}
\define@key{Hyp}{pdfurl}{\hyxmp@pdfstringdef\@pdfurl{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfidentifier}
% Prepare to store an identifier that uniquely represents the document.
%    \begin{macrocode}
\def\@pdfidentifier{}
\define@key{Hyp}{pdfidentifier}{\hyxmp@pdfstringdef\@pdfidentifier{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfsubtitle}
% Prepare to store the document's subtitle.
%    \begin{macrocode}
\def\@pdfsubtitle{}
\define@key{Hyp}{pdfsubtitle}{\hyxmp@pdfstringdef\@pdfsubtitle{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfpubstatus}
% Prepare to store the document's journal article version.
%    \begin{macrocode}
\def\@pdfpubstatus{}
\define@key{Hyp}{pdfpubstatus}{\hyxmp@pdfstringdef\@pdfpubstatus{#1}}
%    \end{macrocode}
% \end{macro}
%
% The following eight macros---|\@pdfcontactaddress|,
% |\@pdfcontactcity|, |\@pdfcontactregion|, |\@pdfcontactpostcode|,
% |\@pdfcontactcountry|, |\@pdfcontactphone|, |\@pdfcontactemail|, and
% |\@pdfcontacturl|---together specify how to contact the person or
% institution responsible for the document.
%
% \begin{macro}{\@pdfcontactaddress}
% Prepare to store a street address for the document's contact
% person\slash institution.  The \acro{IPTC} standard defines this as
% follows:
%
% \begin{quote}
%   The contact information address part. Comprises an optional company
%   name and all required information to locate the building or postbox
%   to which mail should be sent. To that end, the address is a
%   multiline field.
% \end{quote}
%
% For consistency with the rest of \pkgname{hyperxmp}, we use commas to
% separate terms, in this case, lines of the address.  The author can
% use |\xmpquote| and |\xmpcomma| to include literal commas.
%    \begin{macrocode}
\def\@pdfcontactaddress{}
\define@key{Hyp}{pdfcontactaddress}{%
  \let\xmpcomma=\hyxmp@comma
  \def\xmpquote##1{##1}%
  \hyxmp@pdfstringdef\@pdfcontactaddress{#1}%
  \def\xmpcomma{,}%
  \let\xmpquote=\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactcity}
% Prepare to store the city of the document's contact person\slash
% institution.
%    \begin{macrocode}
\def\@pdfcontactcity{}
\define@key{Hyp}{pdfcontactcity}{\hyxmp@pdfstringdef\@pdfcontactcity{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactregion}
% Prepare to store the state or province of the document's contact
% person\slash institution.
%    \begin{macrocode}
\def\@pdfcontactregion{}
\define@key{Hyp}{pdfcontactregion}{\hyxmp@pdfstringdef\@pdfcontactregion{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactpostcode}
% Prepare to store the postal code of the document's contact
% person\slash institution.
%    \begin{macrocode}
\def\@pdfcontactpostcode{}
\define@key{Hyp}{pdfcontactpostcode}{\hyxmp@pdfstringdef\@pdfcontactpostcode{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactcountry}
% Prepare to store the country of the document's contact person\slash
% institution.
%    \begin{macrocode}
\def\@pdfcontactcountry{}
\define@key{Hyp}{pdfcontactcountry}{\hyxmp@pdfstringdef\@pdfcontactcountry{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactphone}
% Prepare to store the telephone number of the document's contact
% person\slash institution.
%    \begin{macrocode}
\def\@pdfcontactphone{}
\define@key{Hyp}{pdfcontactphone}{\hyxmp@pdfstringdef\@pdfcontactphone{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontactemail}
% Prepare to store the email address of the document's contact
% person\slash institution.
%    \begin{macrocode}
\def\@pdfcontactemail{}
\define@key{Hyp}{pdfcontactemail}{\hyxmp@pdfstringdef\@pdfcontactemail{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@pdfcontacturl}
% Prepare to store the \acro{URL} of the document's contact person\slash
% institution.
%    \begin{macrocode}
\def\@pdfcontacturl{}
\define@key{Hyp}{pdfcontacturl}{\hyxmp@pdfstringdef\@pdfcontacturl{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@no@info@lists}
% Suppress \pkgname{hyperref} from writing \pdfterm{Author} and
% \pdfterm{Keywords} into the \pdfterm{Info} dictionary.  This prevents
% conflicts between the \acro{PDF} metadata and the \acro{XMP} metadata
% that cause \acro{PDF/A} validation to fail.  The \acro{PDF} metadata
% can be restored by passing the \optname{keeppdfinfo} option to
% |\hypersetup|.
% \changes{v4.0}{2019/03/31}{Added this macro}
% \changes{v5.0}{2020/03/10}{Renamed this macros from
%   \protect\cs{hyxmp@suppress@pdf@metadata} and rewrote it to replace,
%   if possible, only \protect\pdfterm{Author} and \protect\pdfterm{Keywords}}
%    \begin{macrocode}
\def\hyxmp@no@info@lists{%
%    \end{macrocode}
% \begin{macro}{\hyxmp@suppress@pdf@info}
% \begin{macro}{\next}
% If |\patchcmd| fails for any reason---most likely, a modification to
% the \pkgname{hyperref} package---our fallback is to prevent
% \pkgname{hyperref} from writing \emph{any} data to the \acro{PDF}
% \pdfterm{Info} dictionary.
%    \begin{macrocode}
  \def\hyxmp@suppress@pdf@info{%
    \global\let\PDF@FinishDoc=\@empty
    \PackageWarningNoLine{hyperxmp}{%
      Suppressing the _entire_ PDF Info dictionary.\MessageBreak
      Please notify the hyperxmp maintainer%
    }%
  }%
  \let\next=\relax
  \patchcmd
    {\PDF@FinishDoc}%
    {/Author(\@pdfauthor)}%
    {}%
    {}%
    {\let\next=\hyxmp@suppress@pdf@info}%
  \patchcmd
    {\PDF@FinishDoc}%
    {/Keywords(\@pdfkeywords)}%
    {}%
    {}%
    {\let\next=\hyxmp@suppress@pdf@info}%
  \next
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%    \begin{macrocode}
\define@key{Hyp}{keeppdfinfo}[true]{%
  \gdef\hyxmp@no@info@lists{}%
}
%    \end{macrocode}
%
% \changes{v2.1}{2012/09/16}{Enabled \protect\pkgname{hyperxmp} and
%   \protect\pkgname{hyperref} to be loaded in either order.  This addresses
%   a bug report by Yury Donskoy}
%
% We need to capture list arguments (viz.~\optname{pdfauthor} and
% \optname{pdfkeywords}) before \pkgname{hyperref} converts them to
% \term{PDFDocEncoding}.  Otherwise, |\xmpcomma| is permanently replaced
% with a comma, and we lose our ability to change it to a
% |\hyxmp@comma|.  We therefore need to augment \pkgname{hyperref}'s
% option processing with our own.  Because \pkgname{hyperref} has not
% yet been loaded we need to ensure that our augmentation gets loaded in
% the future: after the |\usepackage{hyperref}| but before options are
% passed to that package.
%
% For lack of a better approach, \pkgname{hyperxmp} redefines
% |\ProcessKeyvalOptions| to alter the way \pkgname{hyperref} processes
% \optname{pdfauthor} and \optname{pdfkeywords}.  This is somewhat
% heavy-handed as it gets executed for \emph{every} subsequently loaded
% package that uses |\ProcessKeyvalOptions|, but at least it does what
% we need.  \pkgname{hyperxmp} also redefines |\hypersetup| to do the
% same thing.  This is required in case \pkgname{hyperref} is loaded
% before \pkgname{hyperxmp}.
%
% \begin{macro}{\hyxmp@pdfauthor}
% \begin{macro}{\hyxmp@pdfkeywords}
% Prepare to store the name of the author and a list of keywords.
%    \begin{macrocode}
\def\hyxmp@pdfauthor{}
\def\hyxmp@pdfkeywords{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@redefine@Hyp}
% If not already redefined, redefine \pkgname{hyperref}'s
% \optname{pdfauthor} and \optname{pdfkeywords} options to properly
% handle |\xmpcomma| and |\xmpquote|.
% \changes{v2.1}{2012/09/16}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@redefine@Hyp}{%
%    \end{macrocode}
% \begin{macro}{\hyxmp@Hyp@pdfauthor}
% Store the old definition of |\KV@Hyp@pdfauthor| in
% |\hyxmp@Hyp@pdfauthor|, but only if we see that |\KV@Hyp@pdfauthor| is
% defined and |\hyxmp@Hyp@pdfauthor| isn't.  Otherwise, we'd be defining
% |\hyxmp@Hyp@pdfauthor| in terms of itself and creating an infinite
% loop.
%    \begin{macrocode}
  \@ifundefined{KV@Hyp@pdfauthor}{}{%
    \@ifundefined{hyxmp@Hyp@pdfauthor}{%
      \expandafter\let\expandafter\hyxmp@Hyp@pdfauthor
        \csname KV@Hyp@pdfauthor\endcsname
    }{}%
  }%
%    \end{macrocode}
% \Needspace{6\baselineskip}
% \begin{macro}{\KV@Hyp@pdfauthor}
% \begin{macro}{\xmpcomma}
% \begin{macro}{\xmpquote}
% \begin{macro}{\hyxmp@and}
% \begin{macro}{\and}
% \begin{macro}{\hyxmp@pdfauthor}
% \begin{macro}{\@pdfauthor}
% Redefine |\KV@Hyp@pdfauthor| to process its argument twice.  The first
% time, |\xmpcomma| is defined as a placeholder character
% (|\hyxmp@comma|) and |\xmpquote| as the identity function.  The result
% is stored in |\hyxmp@pdfauthor| for use in structured lists (those
% surrounding each entry with |<rdf:li>|).  The second time, |\xmpcomma|
% is defined as an ordinary comma, and |\xmpquote| is defined as a macro
% that puts its argument within double quotes.  The result is stored in
% |\@pdfauthor| for use in unstructured lists (those in which the entire
% list appears within a single pair of tags).  In case
% \optname{pdfauthor} is left unspecified and we copy |\author|'s
% argument to \optname{pdfauthor}, we temporarily redefine |\and| as the
% list separator when producing a structured list and as ``|and|'' when
% producing an unstructured list.
%    \begin{macrocode}
  \define@key{Hyp}{pdfauthor}{%
    \let\xmpcomma=\hyxmp@comma
    \def\xmpquote####1{####1}%
    \let\hyxmp@and=\and
    \def\and{,}%
    \hyxmp@Hyp@pdfauthor{##1}%
    \global\let\hyxmp@pdfauthor=\@pdfauthor
    \def\and{and\space}%
    \def\xmpcomma{,}%
    \def\xmpquote####1{"####1"}%
    \hyxmp@Hyp@pdfauthor{##1}%
    \def\xmpcomma{,}%
    \let\xmpquote=\relax
    \let\and=\hyxmp@and
  }%
%    \end{macrocode}
% \begin{macro}{\hyxmp@Hyp@pdfkeywords}
% The previous block of code now repeats for the keyword list, starting
% by storing the old definition of |\KV@Hyp@pdfkeywords| in
% |\hyxmp@Hyp@pdfkeywords|.
%    \begin{macrocode}
  \@ifundefined{KV@Hyp@pdfkeywords}{}{%
    \@ifundefined{hyxmp@Hyp@pdfkeywords}{%
      \expandafter\let\expandafter\hyxmp@Hyp@pdfkeywords
        \csname KV@Hyp@pdfkeywords\endcsname
    }{}%
  }%
%    \end{macrocode}
% \begin{macro}{\KV@Hyp@pdfkeywords}
% \begin{macro}{\xmpcomma}
% \begin{macro}{\xmpquote}
% \begin{macro}{\hyxmp@pdfkeywords}
% \begin{macro}{\@pdfkeywords}
% Redefine |\KV@Hyp@pdfkeywords| to process its argument twice.  The
% first time, |\xmpcomma| is defined as a placeholder character
% (|\hyxmp@comma|) and |\xmpquote| as the identity function.  The
% result is stored in |\hyxmp@pdfkeywords| for use in structured lists
% (those surrounding each entry with |<rdf:li>|).  The second time,
% |\xmpcomma| is defined as an ordinary comma, and |\xmpquote| is
% defined as a macro that puts its argument within double quotes.  The
% result is stored in |\@pdfkeywords| for use in unstructured lists
% (those in which the entire list appears within a single pair of tags).
%    \begin{macrocode}
  \define@key{Hyp}{pdfkeywords}{%
    \let\xmpcomma=\hyxmp@comma
    \def\xmpquote####1{####1}%
    \hyxmp@Hyp@pdfkeywords{##1}%
    \global\let\hyxmp@pdfkeywords=\@pdfkeywords
    \def\xmpcomma{,}%
    \def\xmpquote####1{"####1"}%
    \hyxmp@Hyp@pdfkeywords{##1}%
    \def\xmpcomma{,}%
    \let\xmpquote=\relax
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@ProcessKeyvalOptions}
% \changes{v2.0}{2012/09/05}{Added this macro}
% \changes{v5.11}{2022/10/02}{Bug fix: Restore
%   \protect\cs{ProcessKeyvalOptions} after first use.  Thanks to
%   Ulrike Fischer for the bug report}
% \begin{macro}{\ProcessKeyvalOptions}
% \changes{v2.0}{2012/09/05}{Added this macro}
% Redefine \pkgname{kvoptions}'s |\ProcessOptions| command to invoke
% |\hyxmp@redefine@Hyp| before performing its normal option processing.
%    \begin{macrocode}
\let\hyxmp@ProcessKeyvalOptions=\ProcessKeyvalOptions
\renewcommand*{\ProcessKeyvalOptions}{%
  \global\let\ProcessKeyvalOptions=\hyxmp@ProcessKeyvalOptions
  \hyxmp@redefine@Hyp
  \hyxmp@ProcessKeyvalOptions
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@hypersetup}
% \changes{v2.1}{2012/09/16}{Added this macro}
% \begin{macro}{\hypersetup}
% \changes{v2.1}{2012/09/16}{Added this macro}
% Redefine \pkgname{hyperref}'s |\hypersetup| command to invoke
% |\hyxmp@redefine@Hyp| before performing its normal option processing.
%    \begin{macrocode}
\let\hyxmp@hypersetup=\hypersetup
\def\hypersetup{%
  \hyxmp@redefine@Hyp
  \hyxmp@hypersetup
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@concated@metadata}
% \begin{macro}{\hyxmp@aep@toks}
% Assume that if the document loaded either \pkgname{babel} or
% \pkgname{polyglossia} it will eventually define one or more languages
% that \pkgname{hyperxmp} can list within a \xmpprop{dc:language}
% element.  As explained in Section~\ref{sec:initial-prep}, we defer the
% invocation of \cs{AtEndPreamble} to the end of the file.
%    \begin{macrocode}
\edef\hyxmp@concated@metadata{}
\expandafter\hyxmp@aep@toks\expandafter=\expandafter{%
  \the\hyxmp@aep@toks
  \AtEndPreamble{%
    \@ifpackageloaded{babel}{%
      \edef\hyxmp@concated@metadata{babel}%
    }{%
      \@ifpackageloaded{polyglossia}{%
        \edef\hyxmp@concated@metadata{polyglossia}%
      }{%
      }%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@warn@if@no@metadata}
% \begin{macro}{\hyxmp@concated@metadata}
% Issue a warning message if the author failed to specify any metadata
% at all.  This excludes metadata that is included automatically such as
% the current timestamp.  Note that we don't consider |\@pdfmetalang| as
% metadata as that value is meaningful only when used in conjunction
% with other information.  We also don't examine |\@pdfapart| or
% |\@pdfaconformance| because those have nonempty default values.
%    \begin{macrocode}
\newcommand*{\hyxmp@warn@if@no@metadata}{%
  \edef\hyxmp@concated@metadata{%
    \hyxmp@concated@metadata
    \@baseurl
    \@pdfauthor
    \@pdfauthortitle
    \@pdfbookedition
    \@pdfbytes
    \@pdfcaptionwriter
    \@pdfcontactaddress
    \@pdfcontactcity
    \@pdfcontactcountry
    \@pdfcontactemail
    \@pdfcontactphone
    \@pdfcontactpostcode
    \@pdfcontactregion
    \@pdfcontacturl
    \@pdfcopyright
    \@pdfcreationdate
    \@pdfdatetime
    \@pdfdoi
    \@pdfeissn
    \@pdfidentifier
    \@pdfisbn
    \@pdfissn
    \@pdfissuenum
    \@pdfkeywords
    \@pdflang
    \@pdflicenseurl
    \@pdfmetadatetime
    \@pdfmoddate
    \@pdfnumpages
    \@pdfpagerange
    \@pdfpublication
    \@pdfpubtype
    \@pdfsubject
    \@pdfsubtitle
    \@pdftitle
    \@pdfuapart
    \@pdfurl
    \@pdfvolumenum
    \@pdfxstandard
  }%
  \ifx\hyxmp@concated@metadata\@empty
    \PackageWarningNoLine{hyperxmp}{%
      \hyxmp@jobname.tex did not specify any metadata to\MessageBreak
      include in the XMP packet.\space\space Please see the\MessageBreak
      hyperxmp documentation for instructions on how to\MessageBreak
      provide metadata values to hyperxmp}%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@check@standards}
% Most \acro{PDF} standards require that certain metadata be present.
% If compliance with a \acro{PDF} standard is claimed but any of the
% metadata it requires are absent, issue a warning message.
% \changes{v5.0}{2020/03/11}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@check@standards}{%
%    \end{macrocode}
% If the \optname{pdfa} option was passed to \pkgname{hyperref} but
% |\@pdfapart| is not set, set it to~|1| and |\@pdfaconformance| to~|B|.
%    \begin{macrocode}
  \ifHy@pdfa
    \@ifmtargexp{\@pdfapart}{%
      \PackageWarningNoLine{hyperxmp}{%
        `pdfa' was passed to hyperref, but `pdfapart' was\MessageBreak
        not specified.\space\space  Setting pdfapart to `1' and\MessageBreak
        pdfaconformance to `B'%
      }%
      \gdef\@pdfapart{1}%
      \gdef\@pdfaconformance{B}%
    }%
    {}%
  \fi
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@standards}
% We define |\hyxmp@standards| to be non-empty if \emph{any} \acro{PDF}
% standard is claimed (currently, \acro{PDF/A}, \acro{PDF/X}, or
% \acro{PDF/UA}.
%    \begin{macrocode}
  \edef\hyxmp@standards{%
    \@pdfapart
    \@pdfxstandard
    \@pdfuapart
  }%
%    \end{macrocode}
% Check that a document title was provided and is non-empty.
%    \begin{macrocode}
  \@ifnotmtargexp{\hyxmp@standards}{%
    \@ifmtargexp{\@pdftitle}{%
      \PackageWarningNoLine{hyperxmp}{%
        Missing pdftitle (required for PDF standards\MessageBreak
        compliance)%
      }%
    }%
    {}%
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@aep@toks}
% Right before we reach the |\begin{document}| we check if
% \pkgname{hyperref} was loaded.  In normal usage, the document will
% already have done a |\usepackage{hyperref}| because otherwise,
% \cs{hypersetup} will not have been defined, and only a limited amount
% of metadata will be included.  However, in case the author is relying
% exclusively on \pkgname{hyperxmp}'s automatically detected metadata,
% we'll need to load \pkgname{hyperref} now.  As explained in
% Section~\ref{sec:initial-prep}, we defer the invocation of
% \cs{AtEndPreamble} to the end of the file.
% \changes{v5.5}{2020/06/24}{Load \protect\pkgname{hyperref} automatically
%   if the document does not do so explicitly, as requested by Robin Schwab}
%    \begin{macrocode}
\expandafter\hyxmp@aep@toks\expandafter=\expandafter{%
  \the\hyxmp@aep@toks
  \AtEndPreamble{%
    \RequirePackage{hyperref}%
%    \end{macrocode}
% Older versions of \pkgname{hyperref} write the \pdfterm{Info}
% dictionary to the \acro{PDF} file at the end of the document.  Newer
% versions of \pkgname{hyperref} write the \pdfterm{Info} dictionary to
% the \acro{PDF} file at the \emph{beginning} of the document.  For
% compatibility with both old and new \pkgname{hyperref} implementations
% we suppress writing the \pdfterm{Info} dictionary here, at the
% beginning of the document.
% \changes{v4.1}{2019/04/02}{Invoke
%   \protect\cs{hyxmp@no@info@lists} at the beginning of the
%   document, for compatibility with both newer and older versions of
%   \protect\pkgname{hyperref}}
%    \begin{macrocode}
    \hyxmp@no@info@lists
%    \end{macrocode}
% If \optname{pdftitle} is undefined but the author invoked \cs{title},
% we copy the latter to the former.  This addresses two problems:
% (1)~handling \LaTeX\ classes in which \cs{maketitle} clears \cs{title}
% and (2)~ensuring that \pkgname{hyperref} writes the same title to the
% \acro{PDF} \pdfterm{Info} dictionary that \pkgname{hyperxmp} writes to
% the \acro{XMP} packet.  We do likewise for \cs{author}~$\rightarrow$
% \optname{pdfauthor}.
%
% One tricky bit is that the standard \LaTeX\ classes do not define
% \cs{@title} and \cs{@author} as empty strings but rather as calls to
% \cs{@latex@warning@no@line} that complain about a missing
% title/author.  Hence, we can't simply test if the title and author are
% empty because they're not.  Instead, we first locally redefine
% \cs{@latex@warning@no@line} to discard its argument then test if any
% text remains.
% \changes{v5.5}{2020/07/24}{Copy \protect\cs{title} to
%   \protect\optname{pdftitle} and \protect\cs{author} to
%   \protect\optname{pdfauthor} at the start of the document to improve
%   consistency between \protect\acro{XMP} and \protect\acro{PDF} metadata}
%    \begin{macrocode}
    \begingroup
      \let\@latex@warning@no@line=\@gobble
      \hyxmp@use@first@valid{pdftitle}{\@pdftitle}{%
        \scr@subject@var,%
        \@title
      }%
      \hyxmp@use@first@valid{pdfauthor}{\@pdfauthor}{%
        \scr@fromname@var,%
        \@author
      }%
    \endgroup
  }%
}
%    \end{macrocode}
% \end{macro}
%
% When we reach the |\end{document}| we need to gather up the metadata
% specified explicitly by the user, infer additional metadata where
% possible, and write the \acro{XMP} packet to the \acro{PDF} file.
% \changes{v1.3}{2011/04/25}{Introduced the \protect\optname{pdfmetalang}
%   package option, which enables an author to specify the language in which he
%   wrote the document's metadata}
% \changes{v2.0}{2012/08/02}{New \cs{AtBeginDocument} code from Heiko
%   Oberdiek to properly encode \cs{@pdfmetalang}}
% \changes{v3.3}{2017/07/21}{Don't overwrite an existing
%   \protect\optname{pdfmetalang} with \protect\optname{pdflang} or
%   \protect\xmpterm{x-default}.  This addresses a bug report by Niklas
%   Beisert}
% \changes{v5.4}{2020/06/18}{Moved the automatic assignment of
%   \protect\cs{@pdflang} and \protect\cs{@pdfmetalang} from
%   \protect\cs{hyxmp@auto@assign@data} to within a call to
%   \protect\cs{hyxmp@at@end}}
% \changes{v5.5}{2020/07/21}{Move most of the \protect\cs{AtEndPreamble}
%   code to \protect\cs{hyxmp@at@end}}
%    \begin{macrocode}
\hyxmp@at@end{%
%    \end{macrocode}
% Fill in any missing metadata we can using values provided by the author
% via mechanisms other than the \cs{hypersetup} command.
%    \begin{macrocode}
  \hyxmp@auto@assign@data
%    \end{macrocode}
% If the document claims to comply with one or more \acro{PDF}
% standards, check that all of the requisite metadata are present.
%    \begin{macrocode}
  \hyxmp@check@standards
%    \end{macrocode}
% We can finally construct the \acro{XMP} packet and write it to the
% \acro{PDF} document catalog.
%    \begin{macrocode}
  \hyxmp@warn@if@no@metadata
  \hyxmp@embed@packet
}
%    \end{macrocode}
%
%
% \subsection{Advanced metadata detection}
%
% \pkgname{hyperxmp} strives to be as convenient and user-friendly as
% possible.  To that end, we try to automatically detect as much
% metadata as possible.  The author can of course augment or override
% autodetected metadata by explicitly providing values to
% \cs{hypersetup}, but the hope is that we can save the author some
% effort in many cases.
%
% In this section, we identify additional metadata we can use.  Most of
% the functionality is class- or package-specific.  For example, we
% check for phone numbers provided to the \Koma\ letter classes via
% |\setkomavar{fromphone}{|\dots|}| and/or
% |\setkomavar{frommobilephone}{|\dots|}|, street addresses provided to
% the \ACMclass\ article class via \cs{affiliation}, and languages
% the \pkgname{polyglossia} package is instructed to load via
% \cs{setdefaultlanguage} and \cs{setotherlanguage}.
%
% \begin{macro}{\hyxmp@set@koma@phones}
% \changes{v5.3}{2020/06/07}{Added this macro}
% \changes{v5.5}{2020/07/08}{Support hyperlinks and other markup in
%   \protect\texttt{frommobilephone} and \protect\texttt{fromphone},
%   as requested by Robin Schwab}
% \begin{macro}{\hyxmp@koma@phones}
% Define \cs{hyxmp@koma@phones} as a comma-separated list of the phone
% numbers provided to a \Koma\ letter class (mobile and landline).
%    \begin{macrocode}
\newcommand*{\hyxmp@set@koma@phones}{%
  \begingroup
    \Hy@unicodefalse
    \@if@def@and@nonempty{scr@frommobilephone@var}{%
      \@if@def@and@nonempty{scr@fromphone@var}{%
        \hyxmp@pdfstringdef\hyxmp@koma@phones{\scr@frommobilephone@var,\scr@fromphone@var}%
      }{%
        \hyxmp@pdfstringdef\hyxmp@koma@phones{\scr@frommobilephone@var}%
      }%
    }{%
      \@if@def@and@nonempty{scr@fromphone@var}{%
        \hyxmp@pdfstringdef\hyxmp@koma@phones{\scr@fromphone@var}%
      }{%
      }%
    }%
  \endgroup
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@use@first@valid}
% Given a \pkgname{hyperxmp} option~(|#1|), its current value~(|#2|),
% and a comma-separated list of option names~(|#3|), if the current
% value is empy, invoke \cs{hypersetup} to set the option to the first
% non-empty item in the list.  If all items in the list are empty, do
% nothing.
% \changes{v5.3}{2020/05/29}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@use@first@valid}[3]{%
  \@ifmtargexp{#2}{%
    \hyxmp@use@first@valid@i{#1}#3,!,%
  }%
  {}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@use@first@valid@i}
% This macro performs all the work for \cs{hyxmp@use@first@valid}.  It
% loops over a comma-separated list of macros~(|#2|), stopping when it
% encounters an end-of-list marker~(``|!|'').  The first list element
% that is neither undefined nor empty is assigned to a given option
% name~(|#1|) using \cs{hypersetup}.
%    \begin{macrocode}
\def\hyxmp@use@first@valid@i#1#2,{%
  \def\next{\hyxmp@use@first@valid@i{#1}}%
  \ifx#2!%
    \let\next=\relax
  \else
    \ifx#2\undefined
    \else
      \@ifnotmtargexp{#2}{%
        \hypersetup{#1={#2}}%
        \def\next##1!,{}%
      }%
    \fi
  \fi
  \next
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@auto@assign@data}
% If certain metadata are unspecified, try to specify meaningful values
% using data provided by author via other means (e.g.,~\cs{title} for
% the document's title).
%    \begin{macrocode}
\newcommand*{\hyxmp@auto@assign@data}{%
%    \end{macrocode}
% If \cs{@pdflang} is not set, see if we can detect the document
% language via either the \pkgname{babel} or \pkgname{polyglossia}
% packages.
%    \begin{macrocode}
  \@if@def@and@nonempty{@pdflang}{%
    \let\hyxmp@dc@lang=\@pdflang
  }{%
    \hyxmp@detect@langs
  }%
%    \end{macrocode}
% Replace an empty \cs{@pdfmetalang}.  If \cs{@pdflang} is defined, use
% that as the metadata language.  Otherwise, use \xmpterm{x-default}.
%    \begin{macrocode}
  \ifx\@pdfmetalang\@empty
    \ifx\@pdflang\@empty
      \let\@pdfmetalang=\hyxmp@x@default
    \else
      \edef\@pdfmetalang{\@pdflang}%
    \fi
  \fi
%    \end{macrocode}
% Identify various author-provided information that can be co-opted
% for use as \acro{XMP} metadata.
% \changes{v2.7}{2016/02/01}{Automatically use \cs{title} and \cs{author}
%   if \protect\optname{pdftitle} and \protect\optname{pdfauthor} are left
%   unspecified.   Thanks to Maciej Radziejewski for the suggestion}
% \changes{v5.3}{2020/05/29}{Consider other author-provided sources of
%   metadata.  Thanks to Robin Schwab for proposing that
%  \protect\pkgname{hyperxmp} use the \Koma\ letter classes's metadata}
% \changes{v5.5}{2020/07/24}{Moved the language-detection and
%   \protect\XeTeX\ date-detection code here from the
%   \protect\cs{hyxmp@at@end} block}
% \changes{v5.5}{2020/07/24}{Use \protect\LuaTeX\ mechanisms, when available,
%   to automatically compute the page count}
% \changes{v5.5}{2020/07/24}{Moved title and author autodetection to the
%   \protect\cs{AtEndPreamble}}
%    \begin{macrocode}
  \hyxmp@use@first@valid{pdfcontactemail}{\@pdfcontactemail}{%
    \scr@fromemail@var
  }%
  \hyxmp@set@koma@phones
  \hyxmp@use@first@valid{pdfcontactphone}{\@pdfcontactphone}{%
    \hyxmp@koma@phones
  }%
  \hyxmp@use@first@valid{pdfcontacturl}{\@pdfcontacturl}{%
    \scr@fromurl@var
  }%
  \hyxmp@use@first@valid{pdfsubtitle}{\@pdfsubtitle}{%
    \@subtitle
  }%
  \hyxmp@use@first@valid{pdfpublisher}{\@pdfpublisher}{%
    \@publishers
  }%
%    \end{macrocode}
% We handle the \clsname{acmart} class specially.  \clsname{acmart}
% stores author-provided contact information in a structured format that
% we can process fairly easily.  Note that if the author is not using
% the \clsname{acmart} class, \cs{hyxmp@parse@acmart} will have been
% redefined to do nothing.
%    \begin{macrocode}
  \hyxmp@parse@acmart
%    \end{macrocode}
% Most \acro{PDF} standards dictate that if the same metadata appear in
% both the \acro{XMP} packet and the \acro{PDF} \pdfterm{Info}
% dictionary, the metadata must match.  This requirement poses a problem
% for a user-unspecified \optname{pdfcreationdate} in the context of
% \XeLaTeX\@.  In this case we explicitly define |\@pdfcreationdate| as
% |\hyxmp@today@pdf| to prevent the \cmdname{xdvipdfmx} back-end
% processor from detecting a missing \pdfterm{CreationDate} in the
% \pdfterm{Info} dictionary and adding its own---typically a few seconds
% after \pkgname{hyperxmp} has constructed an \xmpprop{xmp:CreateDate}
% for the \acro{XMP} metadata and leading to a metadata mismatch.
%    \begin{macrocode}
  \@ifundefined{XeTeXversion}{}{%
    \@ifmtargexp{\@pdfcreationdate}{%
      \let\@pdfcreationdate=\hyxmp@today@pdf
    }%
    {}%
  }%
%    \end{macrocode}
% Query the document currently being built for page and byte counts.
%    \begin{macrocode}
  \hyxmp@query@self
}
%    \end{macrocode}
% \end{macro}
%
% Determine the size of the output file from the \emph{previous} run of
% \LuaLaTeX\@.  This action has to be performed before the
% |\begin{document}| because at that point the size of the output file
% is reset to zero.  We use |\jobname.pdf| as the name of the output
% file because |status.output_file_name| is not defined at this point.
%
% It's possible to use \pdfLaTeX's \cs{pdffilesize} primitive to query
% the size of |\jobname.pdf| under \pdfLaTeX\@.  Unfortunately, doing so
% has a side effect of making \progname{latexmk} view the
% \acro{PDF} file as an input file, which puts \progname{latexmk} in an
% infinite build loop.  (This was the case for \pkgname{hyperxmp} v5.5
% and v5.6.)  See the discussion at
% \url{https://github.com/borisveytsman/acmart/issues/413} for more
% information.
% \changes{v5.7}{2020/11/01}{Do not automatically compute the
%   \protect\acro{PDF} file size under \protect\pdfLaTeX\ because this confuses
%   \protect\progname{latexmk}.  Thanks to John Collins, Nelson Posse Lago,
%   Derek Dreyer, and the other contributors to
%   \protect\href{https://github.com/borisveytsman/acmart/issues/413}{\protect\pkgname{acmart} issue \#413},
%   ``Latexmk goes into an infinite loop even on sample files from ACM''}
% \changes{v5.8}{2020/11/05}{Take
%   \protect\mbox{\protect\texttt{-\kern0pt-output-directory}} into
%   consideration when querying the output file size.  Thanks to John
%   Collins for pointing out that the user can change the output
%   directory}
%    \begin{macrocode}
\ifLuaTeX
%    \end{macrocode}
% Now that we know we're running \LuaLaTeX\ we define a Lua function,
% |get_pdf_size|, that takes the base name of the output file and
% returns the number of bytes in the corresponding \acro{PDF} file.  One
% difficulty is that, at the time of this writing, \LuaTeX\ lacks a
% mechanism for querying the full name of the output file.  Our
% workaround is a tad kludgy but seems to work.  We walk the list of
% command-line arguments for
% \mbox{``|-\kern0pt-output-directory=|\meta{dir}''}.  (We in fact
% accept either one or two initial dashes and abbreviations as terse as
% \mbox{``|-output-d|''}.)  Then, we concatenate the output directory
% (or ``|.|'' if unspecified), a path separator, the given base name of
% the job, and a ``|.pdf|'' extension.  Alas, different operating
% systems use different path separators so we have to query the
% operating-system type to select an appropriate separator: ``|\|'' on
% Windows/\acro{DOS} and ``|/|'' on everything else.
%
% |get_pdf_size| is called regardless of whether we're producing
% \acro{PDF} or \acro{DVI} output.  We assume that even if the user
% specified |--output-format=dvi|, the user's intention is eventually to
% convert the document to \acro{PDF}.
%    \begin{macrocode}
  \begin{luacode*}
function get_pdf_size (bname)
%    \end{macrocode}
% Search the list of command-line arguments for the output directory.
%    \begin{macrocode}
   local odir = ""
   for _, opt in ipairs(arg) do
      local m = string.match(opt, "%-output%-d.-=(.*)")
      if m then
         odir = m
      end
   end
%    \end{macrocode}
% Set the path separator to either ``|/|'' or ``|\|'', depending on the
% operating system.
%    \begin{macrocode}
   local sep = "/"
   if os.type == "windows" or os.type == "msdos" then
      sep = "\\\\"
   end
%    \end{macrocode}
% Concatenate the output directory, path separator, base name, and
% \texttt{.pdf} extension.  Do not insert a path separator if either
% (1)~no output directory was specified, (2)~the output directory
% already ends with the path separator, or (3)~the output directory ends
% in a colon (and is therefore a relative directory) on
% Windows/\acro{DOS}.  As a few examples,
%
% \bigskip
% \noindent
% \begingroup
% \let\bs=\textbackslash
% \begin{tabular}{@{\quad\textbullet~}l@{~+~}l@{~+~}l@{~+~``\texttt{.pdf}''~=~}l@{}}
% ``'' & ``\texttt{/}'' & ``\texttt{myfile}''
% & ``\texttt{myfile.pdf}'' \\
% ``\texttt{/docs}'' & ``\texttt{/}'' & ``\texttt{myfile}''
% & ``\texttt{/docs/myfile.pdf}'' \\
% ``\texttt{/docs/}'' & ``\texttt{/}'' & ``\texttt{myfile}''
% & ``\texttt{/docs/myfile.pdf}'' \\
% ``\texttt{C:\bs docs}'' & ``\texttt{\bs}'' & ``\texttt{myfile}''
% & ``\texttt{C:\bs docs\bs myfile.pdf}'' \\
% ``\texttt{C:\bs docs\bs}'' & ``\texttt{\bs}'' & ``\texttt{myfile}''
% & ``\texttt{C:\bs docs\bs myfile.pdf}'' \\
% ``\texttt{C:\bs}'' & ``\texttt{\bs}'' & ``\texttt{myfile}''
% & ``\texttt{C:\bs myfile.pdf}'' \\
% ``\texttt{C:}'' & ``\texttt{\bs}'' & ``\texttt{myfile}''
% & ``\texttt{C:myfile.pdf}'' \\
% \end{tabular}
% \endgroup
% \bigskip
%    \begin{macrocode}
   local dlast = string.sub(odir, -1)
   if odir == "" or dlast == sep or (dlast == ":" and sep == "\\\\") then
      sep = ""
   end
   local fname = odir .. sep .. bname .. ".pdf"
%    \end{macrocode}
% Query the file size and return it.
%    \begin{macrocode}
   local nbytes = lfs.attributes(fname, "size")
   return nbytes
end
  \end{luacode*}
%    \end{macrocode}
% Now that we've defined |get_pdf_size| we invoke it, passing it
% \cs{hyxmp@jobname} as the base name of the job.  (Recall that
% \cs{hyxmp@jobname} is the same as \cs{jobname} but with any
% surrounding double quotes removed.)  We store |get_pdf_size|'s
% output---which will be empty if the \acro{PDF} file doesn't yet
% exist---in \cs{hyxmp@prev@pdf@size}.
%    \begin{macrocode}
  \xdef\hyxmp@prev@pdf@size{%
    \luadirect{
nbytes = get_pdf_size("\hyxmp@jobname")
if nbytes then
    tex.write(nbytes)
end
    }%
  }%
\fi
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@query@self}
% Query the document currently being built to acquire page and byte counts.
% \changes{v5.5}{2020/07/25}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@query@self}{%
%    \end{macrocode}
% \LaTeX's |totalpages| counter tracks the number of pages written.  We
% use this mechanism to assign \cs{@pdfnumpages}.
% \changes{v5.11}{2022/10/16}{Use \protect\cs{thetotalpages} to compute
%   the page count in an engine-independent manner.  Thanks to Ulrike
%   Fischer for recommending this mechanism}
%    \begin{macrocode}
  \@if@def@and@nonempty{@pdfnumpages}{%
  }{%
    \xdef\@pdfnumpages{\thetotalpages}%
  }%
%    \end{macrocode}
% If \optname{pdfbytes} hasn't been set, set it to the output file's size
% from the previous run.
%    \begin{macrocode}
  \hyxmp@use@first@valid{pdfbytes}{\@pdfbytes}{%
    \hyxmp@prev@pdf@size
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@parse@acmart}
% The \clsname{acmart} class stores a rich set of author metadata in its
% \cs{addresses} macro.  \cs{hyxmp@parse@acmart} extracts the contact
% information for the first author and converts that to \acro{XMP}
% metadata.
% \changes{v5.3}{2020/05/30}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@parse@acmart}{%
  \begingroup
%    \end{macrocode}
% \begin{macro}{\@author}
% \clsname{acmart} has already invoked
% |\hypersetup{pdfauthor=|\dots|}| to specify the complete list of
% authors.  At this point, |\@author| is defined to produce a warning
% message.  We locally redefine it to do nothing.
%    \begin{macrocode}
    \let\@author=\@gobble
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\email}
% \begin{macro}{\hyxmp@address@val}
% Within \cs{addresses}, \cs{email} is defined to accept two arguments,
% the second of which is the author's email address.
%    \begin{macrocode}
    \def\email##1##2{%
      \def\hyxmp@address@val{##2}%
      \hyxmp@use@first@valid{pdfcontactemail}{\@pdfcontactemail}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\streetaddress}
% \begin{macro}{\hyxmp@address@val}
% \cs{streetaddress} wraps the author's street address.
%    \begin{macrocode}
    \def\streetaddress##1{%
      \def\hyxmp@address@val{##1}%
      \hyxmp@use@first@valid{pdfcontactaddress}{\@pdfcontactaddress}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\city}
% \begin{macro}{\hyxmp@address@val}
% \cs{city} wraps the author's city name.
%    \begin{macrocode}
    \def\city##1{%
      \def\hyxmp@address@val{##1}%
      \hyxmp@use@first@valid{pdfcontactcity}{\@pdfcontactcity}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\state}
% \begin{macro}{\hyxmp@address@val}
% \cs{state} wraps the author's state or region name.
%    \begin{macrocode}
    \def\state##1{%
      \def\hyxmp@address@val{##1}%
      \hyxmp@use@first@valid{pdfcontactregion}{\@pdfcontactregion}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\country}
% \begin{macro}{\hyxmp@address@val}
% \cs{country} wraps the author's country name.
%    \begin{macrocode}
    \def\country##1{%
      \def\hyxmp@address@val{##1}%
      \hyxmp@use@first@valid{pdfcontactcountry}{\@pdfcontactcountry}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\postcode}
% \begin{macro}{\hyxmp@address@val}
% \cs{postcode} wraps the author's postal code.
%    \begin{macrocode}
    \def\postcode##1{%
      \def\hyxmp@address@val{##1}%
      \hyxmp@use@first@valid{pdfcontactpostcode}{\@pdfcontactpostcode}{%
        \hyxmp@address@val
      }%
    }%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\affiliation}
% We want to produce \acro{XMP} metadata for only a single affiliation.
% Although \cs{hyxmp@use@first@valid} will ensure that only the first
% email, city, country, etc.\ encountered is considered, we run the
% first of one affiliation defining, say, a city and state but no
% country and a subsequent affiliation defining a country.  In that
% case, the \acro{XMP} would include the first author's city and state
% and the subsequent author's country.  Hence, we define
% \cs{affiliation} to ``self destruct'' after its first use, discarding
% all further affiliations.
%    \begin{macrocode}
    \def\affiliation##1##2{%
      ##2%
      \let\affiliation=\@gobbletwo
    }%
%    \end{macrocode}
% \end{macro}
%
% We want to evaluate \cs{addresses} with the preceding local
% definitions in effect, but we don't want to typeset any text appearing
% in the string.  Hence, we ``typeset'' \cs{addresses} within a box that
% is subsequently discarded.
%    \begin{macrocode}
    \setbox0=\hbox{\addresses}%
  \endgroup
%    \end{macrocode}
%
% \clsname{acmart} supports other relevant metadata in addition to the
% authors' mailing addresses.  For instance, papers accepted for
% publication indicate their \acro{DOI} number.  However, papers under
% review will contain either a placeholder \acro{DOI},
% ``10.1145/nnnnnnn.nnnnnnn'', or the example \acro{DOI} specified in
% the \clsname{acmart} example document, ``10.1145/1122445.1122456''.
% We ignore both of those \acro{DOI}s.
% \changes{v5.4}{2020/06/16}{Bug fix: Correct a missing ``else'' argument
%   in two invocations of \protect\cs{@if@def@and@nonempty}}
%    \begin{macrocode}
  \@if@def@and@nonempty{@acmDOI}{%
    \IfSubStr{\@acmDOI}{10.1145/1122445.1122456}{}{%
      \IfSubStr{\@acmDOI}{10.1145/nnnnnnn.nnnnnnn}{}{%
        \hyxmp@use@first@valid{pdfdoi}{\@pdfdoi}{%
          \@acmDOI
        }%
      }%
    }%
  }%
  {}%
%    \end{macrocode}
% \begin{macro}{\hyxmp@strip@isbn@date}
% \begin{macro}{\hyxmp@acm@isbn}
% Papers appearing in conference proceedings specify the proceedings'
% \acro{ISBN}.  As with \cs{@acmDOI} above, we ignore both the
% placeholder \acro{ISBN}, ``978-x-xxxx-xxxx-x/YY/MM'', and the example
% \acro{ISBN}, ``978-1-4503-XXXX-X/18/06''.  We also strip off the
% ``\texttt{/}\meta{year}\texttt{/}\meta{month}'' suffix so as to
% include a true \acro{ISBN} in the \acro{XMP} metadata.
%    \begin{macrocode}
  \@if@def@and@nonempty{@acmISBN}{%
    \IfSubStr{\@acmISBN}{XXXX}{}{%
      \IfSubStr{\@acmISBN}{xxxx}{}{%
        \def\hyxmp@strip@isbn@date##1/##2!{##1}%
        \edef\hyxmp@acm@isbn{%
          \expandafter\hyxmp@strip@isbn@date\@acmISBN/!%
        }%
        \hyxmp@use@first@valid{pdfisbn}{\@pdfisbn}{%
          \hyxmp@acm@isbn
        }%
      }%
    }%
  }%
  {}%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\hyxmp@acm@publisher}
% The publisher is of course \acro{ACM}.
%    \begin{macrocode}
  \def\hyxmp@acm@publisher{Association for Computing Machinery}%
  \hyxmp@use@first@valid{pdfpublisher}{\@pdfpublisher}{%
    \hyxmp@acm@publisher
  }%
%    \end{macrocode}
% Use the journal name if defined, otherwise the book name (for
% conference proceedings).
%    \begin{macrocode}
  \hyxmp@use@first@valid{pdfpublication}{\@pdfpublication}{%
    \@journalName,%
    \@acmBooktitle,%
    \@acmConference
  }%
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\hyxmp@acm@pubtype}
% \clsname{acmart} makes clear whether it's typesetting a journal
% article.  If it's not a journal, we assume it's a book (conference
% proceedings).
%    \begin{macrocode}
  \if@ACM@journal
    \def\hyxmp@acm@pubtype{journal}%
  \else
    \def\hyxmp@acm@pubtype{book}%
  \fi
  \hyxmp@use@first@valid{pdfpubtype}{\@pdfpubtype}{%
    \hyxmp@acm@pubtype
  }%
%    \end{macrocode}
% \end{macro}
% Journal articles have a volume and issue number.
%    \begin{macrocode}
  \hyxmp@use@first@valid{pdfvolumenum}{\@pdfvolumenum}{%
    \@acmVolume
  }%
  \hyxmp@use@first@valid{pdfissuenum}{\@pdfissuenum}{%
    \@acmNumber
  }%
}
%    \end{macrocode}
% \end{macro}
%
% Nullify \cs{hyxmp@parse@acmart} if the author is not using the
% \clsname{acmart} class.
%    \begin{macrocode}
\@ifclassloaded{acmart}{}{\let\hyxmp@parse@acmart=\relax}
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@dc@lang}
% \cs{hyxmp@dc@lang} is a comma-separated list of all languages used in
% the document.
%    \begin{macrocode}
\let\hyxmp@dc@lang=\@empty
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@detect@langs}
% If \optname{pdflang} was not specified, try to determine the document
% language(s) using either \pkgname{babel}'s or \pkgname{polyglossia}'s
% definitions.
% \changes{v5.3}{2020/06/08}{Acquire the default language from the
%   \protect\pkgname{polyglossia} package, if loaded.  Thanks to
%   Robin Schwab for bringing that package to my attention}
% \changes{v5.4}{2020/06/16}{Refactored language detection into a
%   separate command}
% \changes{v5.5}{2020/07/21}{Set the language(s) immediately instead of
%   deferring them to \protect\cs{hyxmp@set@dc@lang}}
%    \begin{macrocode}
\newcommand*{\hyxmp@detect@langs}{%
  \@ifundefined{mainbcp47id}{%
    \@ifundefined{LocaleForEach}{%
%    \end{macrocode}
% The document doesn't appear to have loaded either \pkgname{babel} or
% \pkgname{polyglossia}.  In this case we have one small task to do.  In
% older versions of \pkgname{hyperref}, \cs{@pdflang} is set to
% \cs{@empty} if \optname{pdflang} is not specified.  In newer versions
% of \pkgname{hyperref}, \cs{@pdflang} is set to \cs{relax} if
% \optname{pdflang} is not specified.  The latter is a bit problematic
% for \pkgname{hyperxmp} because it makes \cs{@pdflang} non-expandable,
% which causes a literal ``\cs{@pdflang}'' to be written as \acro{XMP}
% metadata.  To avoid that situation we explicitly set \cs{@pdflang} to
% \cs{@empty} to avoid problems with non-expandable symbols.
% \changes{v2.3a}{2013/04/16}{Bug fix: Redefine \cs{@pdflang} as
%   \cs{@empty} when \protect\pkgname{hyperref} has set
%   it to \cs{relax}}
%    \begin{macrocode}
      \let\@pdflang=\@empty
    }{%
%    \end{macrocode}
% \changes{v5.4}{2020/06/17}{Added support for \protect\pkgname{babel}}
% \changes{v5.5}{2020/07/16}{Store the main language in \protect\cs{@pdflang}.
%   Thanks to Javier Bezos for his help with the \protect\pkgname{hyperxmp}
%   code and for modifying \protect\pkgname{babel} for
%   \protect\pkgname{hyperxmp}'s benefit}
% \begin{macro}{\hyxmp@dc@lang}
% \begin{macro}{\hyxmp@lang@tag}
% \begin{macro}{\hyxmp@lang@name}
% \begin{macro}{\@pdflang}
% Use \pkgname{babel}'s \cs{LocaleForEach} and \cs{getlocaleproperty} to
% set \cs{@pdflang} to the document's main language and
% \cs{hyxmp@dc@lang} to a comma-separated list of all languages used.
%    \begin{macrocode}
      \BabelEnsureInfo
      \LocaleForEach{%
        \getlocaleproperty\hyxmp@lang@tag{##1}{identification/tag.bcp47}%
        \ifx\hyxmp@dc@lang\@empty
          \xdef\hyxmp@dc@lang{\hyxmp@lang@tag}%
        \else
          \xdef\hyxmp@dc@lang{\hyxmp@dc@lang,\hyxmp@lang@tag}%
        \fi
        \def\hyxmp@lang@name{##1}%
        \ifx\hyxmp@lang@name\bbl@main@language
          \edef\@pdflang{\hyxmp@lang@tag}%
        \fi
      }%
    }%
  }{%
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% Use \pkgname{polyglossia}'s \cs{mainbcp47id} as the document's main
% language and its \cs{xpg@bcp@loaded} as a comma-separated list of all
% document languages.
%    \begin{macrocode}
    \xdef\@pdflang{\csname mainbcp47id\endcsname}%
    \edef\hyxmp@dc@lang{\xpg@bcp@loaded}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Manipulating author-supplied data}
%
% The author provides metadata information to \pkgname{hyperxmp} via
% package options to \pkgname{hyperref} or via \pkgname{hyperref}'s
% |\hypersetup| command.  The functions in this section convert
% author-supplied lists (e.g.,~|pdfkeywords={foo, bar, baz}|) into
% \LaTeX\ lists (e.g.,~|\@elt {foo}| |\@elt {bar}| |\@elt {baz}|) that
% can be more easily manipulated (Section~\ref{sec:list-manip}); parse
% dates in both \acro{PDF} and \acro{XMP} formats
% (Section~\ref{sec:date-manip}; trim spaces off the ends of strings
% (Section~\ref{sec:trim-spaces}); convert text to \acro{XML}
% (e.g.,~from |<scott+hyxmp@pakin.org>| to
% |&lt;scott+hyxmp@pakin.org&gt;|) (Section~\ref{sec:text-xml});
% simplify the pretty-printing of a begin tag, \acro{XML} text, and end
% tag (Section~\ref{sec:output-xml}; and provide metadata in multiple
% languages (Section~\ref{sec:lang-alt}).
%
% \subsubsection{List manipulation}
% \label{sec:list-manip}
%
% We define a macro for converting a list of comma-separated elements
% (e.g.,~the list of \acro{PDF} keywords) to a list of \LaTeX\
% |\@elt|-separated elements.
%
% \begin{macro}{\hyxmp@commas@to@list}
% Given a macro name~(|#1|) and a comma-separated list~(|#2|), define
% the macro name as the elements of the list, each preceded by |\@elt|.
% (Executing the macro therefore applies |\@elt| to each element in
% turn.)
%    \begin{macrocode}
\newcommand*{\hyxmp@commas@to@list}[2]{%
  \gdef#1{}%
  \expandafter\hyxmp@commas@to@list@i\expandafter#1#2,,%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@commas@to@list@i}
% \begin{macro}{\next}
% Recursively construct macro~|#1| from comma-separated list~|#2|.  Stop
% if |#2| is empty.
%    \begin{macrocode}
\def\hyxmp@commas@to@list@i#1#2,{%
  \gdef\hyxmp@sublist{#2}%
  \ifx\hyxmp@sublist\@empty
    \let\next=\relax
  \else
    \hyxmp@trimspaces\hyxmp@sublist
    \@cons{#1}{{\hyxmp@sublist}}%
    \def\next{\hyxmp@commas@to@list@i{#1}}%
  \fi
  \next
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\xmpcomma}
% Because \pkgname{hyperxmp} splits lists at commas, a comma cannot
% normally be used within a list.  We there provide an |\xmpcomma| macro
% that can expand to either a true comma or a placeholder character
% depending on the situation.  Here, we bind it to a comma so it can be
% used in \emph{any} \pkgname{hyperxmp} option, not just those that treat
% commas specially.
% \changes{v2.0}{2012/08/25}{Added this macro}
% \changes{v2.2}{2012/12/07}{Changed the default from
%   \texttt{\string\string\string\relax} to an ordinary comma}
%    \begin{macrocode}
\def\xmpcomma{,}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@comma}
% This is what |\xmpcomma| maps to during list construction.  We assume
% that documents will never otherwise use an \acro{ETX} (|^^C|)
% character in their \acro{XMP} metadata.
% \changes{v2.0}{2012/08/25}{Added this macro}
%    \begin{macrocode}
\bgroup
  \catcode`\^^C=11
  \gdef\hyxmp@comma{^^C}
\egroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@uscore}
% This is what |\_| temporarily maps to during packet construction.
% Because underscores are replaced by spaces, we need a mechanism to
% preserve user-specified underscores (e.g.,~in email addresses).  We
% assume that documents will never otherwise use an \acro{NAK} (|^^U|)
% character in their \acro{XMP} metadata.
% \changes{v2.5}{2014/06/19}{Added this macro}
%    \begin{macrocode}
\bgroup
  \catcode`\^^U=11
  \gdef\hyxmp@uscore{^^U}
\egroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\xmpquote}
% Adobe Acrobat likes to see double quotes around list elements that
% contain commas when the entire list appears within a single \acro{XMP}
% tag (e.g.,~|<pdf:Keywords>|).  However, it doesn't like to see double
% quotes around list elements that contain commas when the list is
% broken up into individual components (i.e.,~using |<rdf:li>| tags).
% We therefore introduce an |\xmpquote| macro that quotes or doesn't
% quote its argument based on context.  Here, we bind |\xmpquote| to
% |\relax| to prevent it from prematurely quoting or not quoting.
% \changes{v2.0}{2012/09/10}{Added this macro}
%    \begin{macrocode}
\let\xmpquote=\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\xmptilde}
% As a convenience for the user, we define |\xmptilde| as a category~12
% (other) ``|~|'' character.
% \changes{v2.4}{2014/01/01}{Added this macro}
%    \begin{macrocode}
\bgroup
  \catcode`\~=12%
  \gdef\xmptilde{~}%
\egroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\XMPTruncateList}
% \changes{v2.0}{2012/09/07}{Added this macro}
% \changes{v2.3b}{2013/07/18}{Made all definitions local to avoid
%   spurious \texttt{Too many unprocessed floats} errors when running
%   with \string\pkgname{memoir}}
% \changes{v4.0}{2019/03/31}{Deprecated this macro}
% \begin{macro}{\hyxmp@temp@str}
% \begin{macro}{\hyxmp@temp@list}
% \begin{macro}{\@elt}
% As a workaround for the inability of older Adobe Acrobat versions to
% display author lists correctly we introduce a hack that replaces a
% list with its first element.  One can then write
% ``|\XMPTruncateList{pdfauthor}|'' and have Adobe Acrobat display the
% author list correctly.
%    \begin{macrocode}
\newcommand{\XMPTruncateList}[1]{{%
    \PackageWarning{hyperxmp}{%
      \noexpand\XMPTruncateList has been deprecated since\MessageBreak
      hyperxmp 4.0 and may be removed in future\MessageBreak
      versions of the package.  \noexpand\XMPTruncateList\MessageBreak
      was found}%
  \edef\hyxmp@temp@str{\csname hyxmp@#1\endcsname}%
  \hyxmp@commas@to@list{\hyxmp@temp@list}{\hyxmp@temp@str}%
  \def\@elt##1{%
    \expandafter\gdef\csname @#1\endcsname{##1}%
    \let\@elt=\@gobble
  }
  \hyxmp@temp@list
}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsubsection{Date manipulation}
% \label{sec:date-manip}
%
% \pkgname{hyperxmp} needs to manipulate two types of date (really,
% timestamp) formats: \acro{PDF} format and \acro{XMP} format.
% \acro{PDF} timestamps are of the form
% ``|D:|\textsc{yyyymmdd}hhmmss|+|\textsc{tt}|'|tt|'|''
% \makeatletter
% \@ifundefined{pdffeedback}{^^A
%   \@ifundefined{pdfcreationdate}{^^A
%   }{^^A
%     (e.g.,~\texttt{\pdfcreationdate})^^A
%   }^^A
% }{^^A
%   (e.g.,~\texttt{\pdffeedback creationdate})^^A
% }
% \makeatother
% ~\cite{Adobe2008:PDF}, while \acro{XMP} timestamps are of the form
% ``\textsc{yyyy}|-|\textsc{mm}|-|\textsc{dd}|T|hh|:|mm|:|ss|+|\textsc{tt}|:|tt''
% \makeatletter
% \@ifundefined{pdffeedback}{^^A
%   \@ifundefined{pdfcreationdate}{^^A
%     \unskip
%   }{^^A
%     (e.g.,~\texttt{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate})^^A
%   }^^A
% }{^^A
%   (e.g.,~\texttt{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate})^^A
% }^^A
% \makeatother
% ~\cite{Adobe2012:XMP}.  The |\hyxmp@as@pdf@date| and
% |\hyxmp@as@xmp@date| macros defined in this section facilitate
% timestamp conversions to \acro{PDF} and \acro{XMP} formats,
% respectively.
%
% \begin{macro}{\hyxmp@first@char}
% \begin{macro}{\hyxmp@first@char@i}
% Return the first character of a string.  This macro is fully expandable.
%    \begin{macrocode}
\def\hyxmp@first@char#1{\hyxmp@first@char@i#1\relax}
\def\hyxmp@first@char@i#1#2\relax{#1}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@as@xmp@date}
% If necessary, convert a timestamp to \acro{XMP} format.  That is, if
% the timestamp is in \acro{PDF} format, convert it; otherwise, leave it
% unmodified.  This macro is fully expandable.
% \changes{v3.2}{2017/02/20}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@as@xmp@date#1{%
  \expandafter\ifnum\expandafter`\hyxmp@first@char@i#1\relax=`D
    \hyxmp@pdf@to@xmp@date{#1}%
  \else
    #1%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdf@to@xmp@date}
% Convert a timestamp from \acro{PDF} format to \acro{XMP} format.  This
% macro is fully expandable.
% \changes{v2.4}{2013/12/24}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@pdf@to@xmp@date#1:#2#3#4#5#6#7#8#9{%
  #2#3#4#5-#6#7-#8#9%
  \hyxmp@parse@time
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@parse@time}
% This is a helper function for |\hyxmp@pdf@to@xmp@date|.
% |\hyxmp@pdf@to@xmp@date| proper parses only the year, month, and day
% then calls |\hyxmp@parse@time|.  |\hyxmp@parse@time| parses the
% hours, minutes, and seconds then calls |\hyxmp@parse@tz@char|.
% \changes{v2.4}{2013/12/24}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@parse@time#1#2#3#4#5#6{%
  T#1#2:#3#4:#5#6%
  \hyxmp@parse@tz@char
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@parse@tz@char}
% This is another helper function for |\hyxmp@pdf@to@xmp@date|.  So far,
% the date and time have been parsed.  |\hyxmp@parse@tz@char| parses the
% first character of the timezone descriptor.  This can be one of
% ``|+|'' for eastern timezones (\mbox{UTC$+x$}, including Asia,
% Oceania, and most of Europe), ``|-|'' for western timezones
% (\mbox{UTC$-x$}, primarily the Americas), or ``|Z|'' for Zulu time
% (\mbox{UTC$+0$}).  Timezones beginning with ``|+|'' or ``|-|'' are
% followed by an offset in hours and minutes (parsed by
% |\hyxmp@parse@tz|; timezones beginning with ``|Z|'' are not.
% \changes{v2.4}{2013/12/24}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@parse@tz@char#1{%
  #1%
  \ifx#1-%
    \expandafter\hyxmp@parse@tz
  \else
    \ifx#1+%
      \expandafter\hyxmp@parse@tz
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@parse@tz}
% This is the final helper function for |\hyxmp@pdf@to@xmp@date|.  It
% parses the piece of the timezone comprising the offset from
% Coordinated Universal Time, measured in hours and minutes.
% \changes{v2.4}{2013/12/24}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@parse@tz#1'#2'{%
  #1:#2%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@as@pdf@date}
% If necessary, convert a timestamp to \acro{PDF} format.  That is, if
% the timestamp is in \acro{XMP} format, convert it; otherwise, leave it
% unmodified.  This macro is fully expandable.
% \changes{v3.2}{2017/02/20}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@as@pdf@date#1{%
  \expandafter\ifx\hyxmp@first@char@i#1\relax D%
    #1%
  \else
    \hyxmp@xmp@to@pdf@date{#1}%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date}
% Convert a timestamp from \acro{XMP} format to \acro{PDF} format.  This
% macro is fully expandable.
% \changes{v2.4}{2013/12/24}{Added this macro}
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date#1{%
  D:\hyxmp@xmp@to@pdf@date@i#1\relax\relax
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@i}
% Parse the year for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@i#1#2#3#4#5#6{%
  #1#2#3#4%
  \ifx#5-%
    \expandafter\hyxmp@xmp@to@pdf@date@ii\expandafter#6%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@ii}
% Parse the month for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@ii#1#2#3#4{%
  #1#2%
  \ifx#3-%
    \expandafter\hyxmp@xmp@to@pdf@date@iii\expandafter#4%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@iii}
% Parse the day for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@iii#1#2#3#4{%
  #1#2%
  \ifx#3T%
    \expandafter\hyxmp@xmp@to@pdf@date@iv\expandafter#4%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@iv}
% Parse the hour for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@iv#1#2#3#4{%
  #1#2%
  \ifx#3:%
    \expandafter\hyxmp@xmp@to@pdf@date@v\expandafter#4%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@v}
% Parse the minute for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@v#1#2#3#4{%
  #1#2%
  \ifx#3:%
    \expandafter\hyxmp@xmp@to@pdf@date@vi\expandafter#4%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@gobbletwo}
% This is exactly the same as \LaTeXe's |\@gobbletwo| but needs to be a
% different literal for |\hyxmp@xmp@to@pdf@date@vii|'s pattern-matching
% to work.
%    \begin{macrocode}
\let\hyxmp@gobbletwo=\@gobbletwo
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@vi}
% Parse the second for |\hyxmp@xmp@to@pdf@date|.  The challenge here is
% that we need to handle four cases for the character following the
% seconds---``|+|'', ``|-|'', ``|Z|'', and no character---without sacrificing
% expandability.  Our tricky solution is to insert a |\@gobbletwo| as a
% sentinel and let |\hyxmp@xmp@to@pdf@date@vi| discard everything up to
% that sentinel (i.e.,~all the other conditionals).
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@vi#1#2#3#4{%
  #1#2%
  \ifx#3+%
    +\expandafter\hyxmp@xmp@to@pdf@date@vii
  \fi
  \ifx#3-%
    -\expandafter\hyxmp@xmp@to@pdf@date@vii
  \fi
  \ifx#3Z%
    Z%
  \fi
  \ifx#3\relax
    \expandafter\hyxmp@gobbletwo
  \fi
  \@gobbletwo #4%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@vii}
% Parse the time-zone hours for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@vii#1\@gobbletwo#2#3#4#5{%
  #2#3%
  \ifx#4:%
    \expandafter\hyxmp@xmp@to@pdf@date@viii\expandafter#5%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmp@to@pdf@date@viii}
% Parse the time-zone minutes for |\hyxmp@xmp@to@pdf@date|.
%    \begin{macrocode}
\def\hyxmp@xmp@to@pdf@date@viii#1#2#3#4{%
  '#1#2'%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@today@xmp@define}
% Use \tex\ primitives to define a given macro as today's date in
% \textsc{yyyy}-\textsc{mm}-\textsc{dd}|T|hh|:|mm|Z| format.
% \changes{v2.4}{2013/12/21}{Added this macro}
% \changes{v3.0}{2016/07/03}{Modified to accept the name of a macro
%   to define}
% \changes{v3.2}{2017/02/21}{Modified to include hours and minutes}
% \changes{v5.0}{2020/03/16}{Modified to specify UTC}
%    \begin{macrocode}
\def\hyxmp@today@xmp@define#1{%
%    \end{macrocode}
% The date is a straightforward representation of \tex's |\year|,
% |\month|, and |\day| primitives, with the latter two zero-padded to
% two digits apiece.
%    \begin{macrocode}
  \xdef#1{\the\year}%
  \ifnum\month<10
    \xdef#1{#1-0\the\month}%
  \else
    \xdef#1{#1-\the\month}%
  \fi
  \ifnum\day<10
    \xdef#1{#1-0\the\day}%
  \else
    \xdef#1{#1-\the\day}%
  \fi
%    \end{macrocode}
% \tex\ does not provide the time in terms of separate hours and minutes
% but rather as the total number of minutes since midnight (|\time|).
% There's no mechanism in \tex\ to query the number of seconds since
% midnight or the timezone so we omit those fields when defining
% macro~|#1|.
%    \begin{macrocode}
  \@hyxmp@count=\time
  \divide\@hyxmp@count by 60
  \ifnum\@hyxmp@count<10
    \xdef#1{#1T0\the\@hyxmp@count}%
  \else
    \xdef#1{#1T\the\@hyxmp@count}%
  \fi
  \multiply\@hyxmp@count by -60
  \advance\@hyxmp@count by \time
  \ifnum\@hyxmp@count<10
    \xdef#1{#1:0\the\@hyxmp@count}%
  \else
    \xdef#1{#1:\the\@hyxmp@count}%
  \fi
  \xdef#1{#1Z}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@try@today}
% If |\hyxmp@today@xmp| is still empty and |#1| is defined, evaluate |#2|.
% Otherwise, do nothing.
%    \begin{macrocode}
\def\hyxmp@try@today#1#2{%
  \@ifmtargexp{\hyxmp@today@xmp}{%
    \@ifundefined{#1}{}{#2}%
  }%
  {}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@today@xmp}
% Define |\hyxmp@today@xmp| as the current date and (if available) time and
% timezone in \acro{XMP} \xmpterm{Date} format~\cite{Adobe2012:XMP}.
% \changes{v2.4}{2013/12/24}{Modified the code to parse the time and
%   timezone from \texttt{\string\string\string\pdfcreationdate}, as
%   proposed by Florian Breitwieser}
% \changes{v5.0}{2020/03/15}{Support \string\XeTeX's \string\cs{filemoddate}}
%    \begin{macrocode}
\def\hyxmp@today@xmp{}
%    \end{macrocode}
% Case 1: |\pdfcreationdate| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
%    \begin{macrocode}
\hyxmp@try@today{pdfcreationdate}{%
  \edef\hyxmp@today@xmp{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate}%
}
%    \end{macrocode}
% Case 2: |\pdffeedback| is defined (\LuaLaTeX~0.85+).
%    \begin{macrocode}
\hyxmp@try@today{pdffeedback}{%
  \edef\hyxmp@today@xmp{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate}%
}
%    \end{macrocode}
% \begin{macro}{\hyxmp@timestamp}
% Case 3: |\filemoddate| is defined (\XeLaTeX).
% In this case, we treat the timestamp of the job's |.log| file as the
% current date/time.
% \label{page:jobname-log}
% \changes{v5.1}{2020/04/08}{Don't rely on
%   \string\cs{jobname}\string\texttt{.aux} existing to query the
%   current time under \string\XeLaTeX\string\@.  Instead, use
%   \string\cs{jobname}\string\texttt{.log}.  Thanks to Ulrike Fischer
%   for the bug report and for her suggestion to use the log file.}
%    \begin{macrocode}
\hyxmp@try@today{filemoddate}{%
  \edef\hyxmp@today@xmp{\filemoddate{\hyxmp@jobname.log}}%
  \edef\next{%
    \edef\noexpand\hyxmp@today@xmp{\noexpand\hyxmp@as@xmp@date{\hyxmp@today@xmp}}%
  }%
  \next
}%
%    \end{macrocode}
% Case 4: None of the above.
% Do the best we can using the available \tex\ primitives (|\year|,
% |\month|, |\day|, and |\time|.
%    \begin{macrocode}
\hyxmp@try@today{year}{%
  \hyxmp@today@xmp@define\hyxmp@today@xmp
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@today@pdf}
% Define |\hyxmp@today@pdf| as the current date and (if available) time
% and timezone in \acro{PDF} date format~\cite{Adobe2008:PDF}.  To do so
% we simply convert |\hyxmp@today@xmp|, defined above, from \acro{XMP}
% to \acro{PDF} using |\hyxmp@xmp@to@pdf@date|.
% \changes{v5.0}{2020/03/16}{Added this macro}
%    \begin{macrocode}
\expandafter\edef\expandafter\hyxmp@today@pdf\expandafter{%
  \expandafter\hyxmp@xmp@to@pdf@date\expandafter{\hyxmp@today@xmp}%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Trimming leading and trailing spaces}
% \label{sec:trim-spaces}
%
% To make it easier for \acro{XMP} processors to manipulate our output we
% define a |\hyxmp@trimspaces| macro to strip leading and trailing
% spaces from various data fields.
%
% \begin{macro}{\hyxmp@trimspaces}
% Redefine a macro as its previous value but without leading or trailing
% spaces.  This code---as well as that for its helper macros,
% |\hyxmp@trimb| and |\hyxmp@trimc|---was taken almost verbatim from a
% solution to an \emph{Around the Bend} puzzle~\cite{Downes1994:ATB15}.
% Inline comments are also taken from the solution text.
%    \begin{macrocode}
\catcode`\Q=3
%    \end{macrocode}
% |\hyxmp@trimspaces\x| redefines |\x| to have the same replacement text
% sans leading and trailing space tokens.
%    \begin{macrocode}
\newcommand{\hyxmp@trimspaces}[1]{%
%    \end{macrocode}
% Use grouping to emulate a multi-token |afterassignment| queue.
%    \begin{macrocode}
  \begingroup
%    \end{macrocode}
% Put ``|\toks 0 {|'' into the |afterassignment| queue.
%    \begin{macrocode}
  \aftergroup\toks\aftergroup0\aftergroup{%
%    \end{macrocode}
% Apply |\hyxmp@trimb| to the replacement text of |#1|, adding a leading
% |\noexpand| to prevent brace stripping and to serve another purpose
% later.
%    \begin{macrocode}
  \expandafter\hyxmp@trimb\expandafter\noexpand#1Q Q}%
%    \end{macrocode}
% Transfer the trimmed text back into |#1|.
%    \begin{macrocode}
  \edef#1{\the\toks0}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@trimb}
% |\hyxmp@trimb| removes a trailing space if present, then calls
% |\hyxmp@trimc| to clean up any leftover bizarre |Q|s, and trim a
% leading space. In order for |\hyxmp@trimc| to work properly we need to
% put back a |Q| first.
%    \begin{macrocode}
\def\hyxmp@trimb#1 Q{\hyxmp@trimc#1Q}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@trimc}
% Execute |\vfuzz| assignment to remove leading space; the |\noexpand|
% will now prevent unwanted expansion of a macro or other expandable
% token at the beginning of the trimmed text.  The |\endgroup| will feed
% in the |\aftergroup| tokens after the |\vfuzz| assignment is
% completed.
%    \begin{macrocode}
\def\hyxmp@trimc#1Q#2{\afterassignment\endgroup \vfuzz\the\vfuzz#1}
\catcode`\Q=11
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Converting text to XML}
% \label{sec:text-xml}
%
% The ``|<|'', ``|>|'', and ``|&|'' characters are significant to \acro{XML}.
% We therefore need to escape them in any author-supplied text.
%
% \begin{macro}{\ifhyxmp@unicodetex}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% \begin{macro}{\hyxmp@unicodetextrue}
% \begin{macro}{\hyxmp@unicodetexfalse}
% \XeTeX\ and \LuaTeX\ natively support \term{Unicode}.  We define the
% conditional |\ifhyxmp@unicodetex| to check for these so we can
% properly handle encoding conversions.  The trick here is that
% \term{Unicode} \tex\ implementations compare decimal~64 to
% hexadecimal~40 (decimal~64), specified with four carets, and take the
% \textsc{true} branch; non-\term{Unicode} \tex\ implementations compare
% decimal~64 to character~``|^|'' (decimal~94), ignore the ``|^^0040|''
% and the rest of the \textsc{true} branch, and take the \textsc{false}
% branch.
%   \begin{macrocode}
\newif\ifhyxmp@unicodetex
\ifnum64=`\^^^^0040\relax
  \hyxmp@unicodetextrue
\else
  \hyxmp@unicodetexfalse
\fi
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\SE->pdfdoc@03}
% Preserve \acro{ETX} (|^^C|), which is normally an invalid character in
% \term{PDFDocEncoding}.  We use it in \pkgname{hyperxmp} (and
% specifically in |\hyxmp@xmlify| below) as a list-element separator.
%    \begin{macrocode}
\expandafter\def\csname SE->pdfdoc@03\endcsname{0003}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\SE->pdfdoc@15}
% Preserve \acro{NAK} (|^^U|), which is normally an invalid character in
% \term{PDFDocEncoding}.  We use it in \pkgname{hyperxmp} (and
% specifically in |\hyxmp@xmlify| below) as a placeholder for an
% underscore character.
%    \begin{macrocode}
\expandafter\def\csname SE->pdfdoc@15\endcsname{0015}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@xmlify}
% \changes{v2.0}{2012/08/02}{Completely rewritten by Heiko Oberdiek to
%   better support Unicode-enabled \TeX\ programs}
% \begin{macro}{\hyxmp@xmlified}
% \begin{macro}{\hyxmp@text}
% Given a piece of text defined using |\pdfstringdef| (i.e.,~with many
% special characters redefined to have category code~11), set
% |\hyxmp@xmlified| to the same text but with all occurrences of~``|<|''
% replaced with~|&lt;|, all occurrences of~``|>|'' replaced with~|&gt;|,
% and all occurrences of~``|&|'' replaced with~|&amp;|.
%    \begin{macrocode}
\newcommand*{\hyxmp@xmlify}[1]{%
  \gdef\hyxmp@xmlified{}%
%    \end{macrocode}
% Escaped \acro{PDF} string~$\rightarrow$ \term{PDFDocEncoding}/\term{Unicode}
%    \begin{macrocode}
  \EdefUnescapeString\hyxmp@text{#1}%
  \ifhyxmp@unicodetex
%    \end{macrocode}
% \term{PDFDocEncoding}/\term{Unicode}~$\rightarrow$ \acro{UTF-32BE}
%    \begin{macrocode}
    \hyxmp@is@unicode\hyxmp@text{%
      \StringEncodingConvert
      \hyxmp@text\hyxmp@text{utf16be}{utf32be}%
    }{%
      \ifXeTeX
        \hyxmp@xetex@crap
      \else
        \StringEncodingConvert
        \hyxmp@text\hyxmp@text{pdfdoc}{utf32be}%
      \fi
    }%
%    \end{macrocode}
% \acro{UTF-32BE}~$\rightarrow$ \acro{UTF-32BE} as hex string
%    \begin{macrocode}
    \EdefEscapeHex\hyxmp@text{\hyxmp@text}%
%    \end{macrocode}
% \acro{UTF-32BE}~$\rightarrow$ \acro{XML} in \acro{ASCII}
%    \begin{macrocode}
    \edef\hyxmp@text{%
      \expandafter
    }\expandafter\hyxmp@toxml@unicodetex\hyxmp@text
    \relax\relax\relax\relax\relax\relax\relax\relax
  \else
%    \end{macrocode}
% \term{PDFDocEncoding}/\term{Unicode}~$\rightarrow$ \acro{UTF-8}
%    \begin{macrocode}
    \hyxmp@is@unicode\hyxmp@text{%
      \StringEncodingConvert
      \hyxmp@text\hyxmp@text{utf16be}{utf8}%
    }{%
      \StringEncodingConvert
      \hyxmp@text\hyxmp@text{pdfdoc}{utf8}%
    }%
%    \end{macrocode}
% \acro{UTF-8}~$\rightarrow$ \acro{UTF-8} as hex string
%    \begin{macrocode}
    \EdefEscapeHex\hyxmp@text{\hyxmp@text}%
%    \end{macrocode}
% \acro{UTF-8} as hex string~$\rightarrow$ \acro{XML} in \acro{UTF-8}
% as hex string
%    \begin{macrocode}
    \edef\hyxmp@text{%
      \expandafter\hyxmp@toxml\hyxmp@text\@empty\@empty
    }%
%    \end{macrocode}
% \acro{XML} in \acro{UTF-8} as hex string~$\rightarrow$ \acro{XML}
% in \acro{UTF-8}
%    \begin{macrocode}
    \EdefUnescapeHex\hyxmp@text{\hyxmp@text}%
  \fi
  \global\let\hyxmp@xmlified\hyxmp@text
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@is@unicode}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% \begin{macro}{\hyxmp@@is@unicode}
% Given a string and two expressions, evaluate the first expression if
% the string is \acro{UTF-16BE}-encoded and the second expression if not.
%    \begin{macrocode}
\begingroup
  \lccode`\<=254 %
  \lccode`\>=255 %
  \catcode254=12 %
  \catcode255=12 %
\lowercase{\endgroup
  \def\hyxmp@is@unicode#1{%
    \expandafter\hyxmp@@is@unicode#1<>\@nil
  }%
  \def\hyxmp@@is@unicode#1<>#2\@nil{%
    \ifx\\#1\\%
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@toxml}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% Replace the characters ``\textless'', ``\&'', and ``\textgreater'' with
% \acro{XML} entities when using a non-native-\term{Unicode}
% \tex\ (\tex\ or \pdfTeX).
%    \begin{macrocode}
\def\hyxmp@toxml#1#2{%
  \ifx#1\@empty
  \else
    \ifnum"#1#2=`\& %
      26616D703B% &amp;
    \else\ifnum"#1#2=`\< %
      266C743B% &lt;
    \else\ifnum"#1#2=`\> %
      2667743B% &gt;
    \else
%    \end{macrocode}
% \cmdname{dvips} wraps text when generating most PostScript code but
% preserves line breaks within strings.  Unfortunately, \cmdname{dvips}
% fails to observe the special case in the PostScript specification that
% ``[b]alanced pairs of parentheses in the string require no special
% treatment''~\cite{Adobe1996:postscript}.  Consequently, \acro{XMP}
% data containing parentheses (e.g.,~``\texttt{Copyright (C) 1605 Miguel
%   de Cervantes}'') confuse \cmdname{dvips} into thinking that the
% string has ended after the closing parenthesis and that line breaks
% can subsequently be injected safely into the document at arbitrary
% points for formatting purposes.  This leads to erroneous display by
% \acro{PDF} viewers, which honor line breaks within \acro{XMP} tags.
% The solution is to insert a backslash before all parentheses when in
% \texttt{pdfmark}-generating mode to convince \cmdname{dvips} that the
% entire \acro{XMP} packet must be treated as a single,
% not-to-be-modified string.
% \changes{v2.0}{2012/08/22}{Escaped parentheses written with
%   \texttt{pdfmark}s to prevent \cmdname{dvips} from line-wrapping the
%   \protect\acro{XMP} packet}
%    \begin{macrocode}
      \@ifundefined{pdfmark}{%
        #1#2%
      }{%
      \ifnum"#1#2=`\( %
        5C28% \(
      \else\ifnum"#1#2=`\) %
        5C29% \)
      \else
        #1#2%
      \fi\fi
      }%
    \fi\fi\fi
    \expandafter\hyxmp@toxml
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@toxml@unicodetex}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% \begin{macro}{\hyxmp@text}
% Replace the characters ``\textless'', ``\&'', and ``\textgreater'' with
% \acro{XML} entities when using a native-\term{Unicode}
% \tex\ (\XeTeX\ or \LuaTeX).
%    \begin{macrocode}
\def\hyxmp@toxml@unicodetex#1#2#3#4#5#6#7#8{%
  \ifx#1\relax
  \else
    \ifnum"#1#2#3#4#5#6#7#8>127 %
      \uccode`\*="#1#2#3#4#5#6#7#8\relax
      \uppercase{%
        \edef\hyxmp@text{\hyxmp@text *}%
      }%
    \else\ifnum"#7#8=`\< %
      \edef\hyxmp@text{\hyxmp@text &lt;}%
    \else\ifnum"#7#8=`\& %
      \edef\hyxmp@text{\hyxmp@text &amp;}%
    \else\ifnum"#7#8=`\> %
      \edef\hyxmp@text{\hyxmp@text &gt;}%
    \else\ifnum"#7#8=`\ %
      \edef\hyxmp@text{\hyxmp@text\space}%
    \else
      \uccode`\*="#7#8\relax
      \uppercase{%
        \edef\hyxmp@text{\hyxmp@text *}%
      }%
    \fi\fi\fi\fi\fi
    \expandafter\hyxmp@toxml@unicodetex
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@skipzeros}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% Skip over leading zeroes in the input argument.
%    \begin{macrocode}
\def\hyxmp@skipzeros#1{%
  \ifx#10%
    \expandafter\hyxmp@skipzeros
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\x}
% \begin{macro}{\hyxmp@xetex@crap}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% \begin{macro}{\hyxmp@try}
% \begin{macro}{\hyxmp@crap@result}
% \begin{macro}{\hyxmp@text}
% In the case of \XeTeX, the strings defined by |\pdfstringdef| can
% contain big characters.  In this case, the string is treated as
% \term{Unicode}.
%    \begin{macrocode}
\begingroup
\def\x#1{\endgroup
  \def\hyxmp@xetex@crap{%
    \edef\hyxmp@try{%
      \expandafter\hyxmp@SpaceOther\hyxmp@text#1\@nil
    }%
    \let\hyxmp@crap@result=N%
    \expandafter\hyxmp@crap@test\hyxmp@try\relax
    \ifx\hyxmp@crap@result Y%
      \let\hyxmp@text\@empty
      \expandafter\hyxmp@crap@convert\hyxmp@try\relax
    \else
      \StringEncodingConvert\hyxmp@text\hyxmp@text{pdfdoc}{utf32be}%
    \fi
  }%
}
\x{ }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@SpaceOther}
% Re-encode all spaces in a string with category code~12 (``other'').
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
%    \begin{macrocode}
\begingroup
  \catcode`\~=12 %
  \lccode`\~=`\ %
\lowercase{\endgroup
  \def\hyxmp@SpaceOther#1 #2\@nil{%
    #1%
    \ifx\relax#2\relax
      \expandafter\@gobble
    \else
      ~%
      \expandafter\@firstofone
    \fi
    {\hyxmp@SpaceOther#2\@nil}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\hyxmp@crap@test}
% Determine if we need to treat a string as \term{Unicode}.
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
%    \begin{macrocode}
\def\hyxmp@crap@test#1{%
  \ifx#1\relax
  \else
    \ifnum`#1>127 %
      \let\hyxmp@crap@result=Y%
      \expandafter\expandafter\expandafter\hyxmp@skiptorelax
    \else
      \expandafter\expandafter\expandafter\hyxmp@crap@test
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@skiptorelax}
% Discard all tokens up to and including the first |\relax|.
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
%    \begin{macrocode}
\def\hyxmp@skiptorelax#1\relax{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@crap@convert}
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
% \begin{macro}{\hyxmp@num}
% \begin{macro}{\hyxmp@text}
% Convert a hexadecimal string to a number.
%    \begin{macrocode}
\def\hyxmp@crap@convert#1{%
  \ifx#1\relax
  \else
    \edef\hyxmp@num{\number`#1}%
    \ifnum\hyxmp@num>"FFFFFF %
      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"1000000}\relax
      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"1000000}}%
    \else
      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
    \fi
    \ifnum\hyxmp@num>"FFFF %
      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"10000}\relax
      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"10000}}%
    \else
      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
    \fi
    \ifnum\hyxmp@num>"FF %
      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"100}\relax
      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"100}}%
    \else
      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
    \fi
    \ifnum\hyxmp@num>0 %
      \lccode`\!=\hyxmp@num\relax
      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
    \else
      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
    \fi
    \expandafter\hyxmp@crap@convert
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@zero}
% Define a null character with category code~12 (``other'').
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
%    \begin{macrocode}
\begingroup
  \catcode0=12 %
  \gdef\hyxmp@zero{^^00}%
\endgroup
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Outputting structured XML}
% \label{sec:output-xml}
%
% An \acro{XMP} packet consists of structured \acro{XML} data.  We
% define some helper routines to handle the repetitive tasks of
% indenting a consistent number of spaces, inserting begin and end tags,
% and escaping arbitrary text as necessary for \acro{XML} compatibility.
%
% \begin{macro}{\hyxmp@extra@indent}
% This macro is used internally to increase the amount of indentation
% when writing certain \acro{XML} data.  It is normally defined as empty
% but can temporarily be redefined to a sequence of |\space| characters.
%    \begin{macrocode}
\newcommand*{\hyxmp@extra@indent}{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple}
% Given an \acro{XMP} tag~(|#1|) and a string~(|#2|), if the string is
% nonempty, add a begin tag, the string, and an end tag to the packet.
% The ``|simple|'' in the macro name indicates that the string is output
% without variations for different languages.
% \changes{v2.0}{2012/08/25}{Added this macro}
% \changes{v5.0}{2020/02/21}{Insert the tag name (\string\texttt{\#1})
%   verbatim}
%    \begin{macrocode}
\newcommand*{\hyxmp@add@simple}[2]{%
  \@ifnotmtargexp{#2}{%
    \hyxmp@xmlify{#2}%
    \hyxmp@add@to@xml{\hyxmp@extra@indent______<}%
    \xdef\hyxmp@xml{\hyxmp@xml#1}%
    \hyxmp@add@to@xml{>\hyxmp@xmlified</}%
    \xdef\hyxmp@xml{\hyxmp@xml#1>^^J}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple@var}
% Given an \acro{XMP} tag~(|#1|) and a variable name~(|#2|), if the
% string is defined, add a begin tag, the string, and an end tag to the
% packet.  The ``|simple|'' in the macro name indicates that the string
% is output without variations for different languages.
% |\hyxmp@add@simple@var| differs from |\hyxmp@add@simple| in that the
% former includes defined but empty values in the \acro{XMP} packet
% while the latter excludes both undefined and defined but empty values.
% \changes{v2.4}{2013/12/21}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@add@simple@var}[2]{%
  \expandafter\ifx\csname#2\endcsname\relax
  \else
    \hyxmp@xmlify{\csname#2\endcsname}%
    \hyxmp@add@to@xml{%
      \hyxmp@extra@indent______<#1>\hyxmp@xmlified</#1>^^J%
    }%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple@lang}
% Given an \acro{XMP} tag~(|#1|) and a string~(|#2|), if the string is
% nonempty, add a begin tag, the string, and an end tag to the packet.
% The ``|simple|'' in the macro name indicates that the string is output
% without variations for different languages.  However, if the string
% begins with a language code in square brackets, specify that as the
% (sole) language for the tag.
% \changes{v4.0}{2019/03/12}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@add@simple@lang}[2]{%
  \@ifnotmtarg{#2}{%
    \hyxmp@xmlify{#2}%
    \expandafter\hyxmp@add@simple@lang@i\hyxmp@xmlified\relax{#1}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple@lang@i}
% This is a helper macro for |\hyxmp@add@simple@lang|.  It takes an
% optional language code (in brackets), text up to |\relax|, and a tag,
% and typesets the text within the \acro{XML} tag.
%    \begin{macrocode}
\newcommand*{\hyxmp@add@simple@lang@i}{%
  \@ifnextchar[\hyxmp@add@simple@lang@ii{\hyxmp@add@simple@lang@ii[\@pdfmetalang]}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple@lang@ii}
% This is another helper macro for |\hyxmp@add@simple@lang|.  It takes
% an mandatory language code (in brackets; can be empty), text up to
% |\relax|, and a tag, and typesets the text within the \acro{XML} tag.
%    \begin{macrocode}
\def\hyxmp@add@simple@lang@ii[#1]#2\relax#3{%
  \@ifnotmtarg{#2}{%
    \hyxmp@xmlify{#2}%
    \@ifmtarg{#1}{%
      \hyxmp@add@to@xml{%
______<#3>\hyxmp@xmlified</#3>^^J%
      }%
    }{%
      \hyxmp@add@to@xml{%
______<#3 xml:lang="#1">\hyxmp@xmlified</#3>^^J%
      }%
    }%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@add@simple@pfx}
% Given an \acro{XMP} tag~(|#1|), a---typically hard-wired---prefix
% string~(|#2|), and a main string~(|#2|), if the main string is
% nonempty, add a begin tag, both strings, and an end tag to the packet.
% The ``|simple|'' in the macro name indicates that the string is output
% without variations for different languages.
% \changes{v5.2}{2020/04/29}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@add@simple@pfx}[3]{%
  \@ifnotmtargexp{#3}{%
    \hyxmp@add@to@xml{\hyxmp@extra@indent______<}%
    \xdef\hyxmp@xml{\hyxmp@xml#1}%
    \hyxmp@pdfstringdef\hyxmp@iprefix{#2}%
    \hyxmp@xmlify{\hyxmp@iprefix}%
    \hyxmp@add@to@xml{>\hyxmp@xmlified}%
    \hyxmp@xmlify{#3}%
    \hyxmp@add@to@xml{\hyxmp@xmlified</}%
    \xdef\hyxmp@xml{\hyxmp@xml#1>^^J}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{Providing metadata in multiple languages}
% \label{sec:lang-alt}
%
% Certain \acro{XMP} tags---\xmpprop{dc:title},
% \xmpprop{dc:description}, and \xmpprop{dc:rights} (and others?  Let me
% know.)---can be expressed in multiple languages.  The same text is
% used for both language \optname{pdfmetalang} (default:
% \optname{pdflang}) and language ``\xmpterm{x-default}''.  To express
% the same metadata in multiple languages, we provide an |\XMPLangAlt|
% macro to construct a list of alternative forms for a piece of
% metadata.
%
% \begin{macro}{\hyxmp@alt@title}
% \begin{macro}{\hyxmp@alt@description}
% \begin{macro}{\hyxmp@alt@rights}
% Each of these macros is a list in which each element is of the form
% ``|\do| \meta{language} \meta{text}'' in which \meta{language} is an
% \acro{ISO} \mbox{639-1} two-letter country code with an optional
% \acro{ISO} \mbox{3166-1} two-letter region code.  For example,
% |\hyxmp@alt@title| may contain an element, ``|\do| |{es-MX}|
% |{Este| |es| |mi| |documento}|''.
%    \begin{macrocode}
\def\hyxmp@alt@title{}
\def\hyxmp@alt@description{}
\def\hyxmp@alt@rights{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@LA@accept}
% This macro wraps |\define@key| to make the option ``|#1|=\meta{value}''
% append \meta{value} to list~|#2|.
%    \begin{macrocode}
\newcommand{\hyxmp@LA@accept}[2]{%
  \define@key{hyxmp@LA}{#1}{%
%    \end{macrocode}
% \begin{macro}{\hyxmp@value}
% As Niklas Beisert observed, if the option passed to the current key
% contains \LaTeX\ code, this code will be included in the \acro{XMP}
% packet, which is undesirable.  Hence, we first clean up the string
% using |\hyxmp@pdfstringdef|.
%    \begin{macrocode}
    \hyxmp@pdfstringdef\hyxmp@value{##1}%
    \xdef#2{#2\noexpand\do {\hyxmp@cur@lang} {\hyxmp@value}}%
  }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% Define \meta{key}=\meta{value} options for appending to each of the
% |\hyxmp@alt|\meta{tag} lists.
%    \begin{macrocode}
\hyxmp@LA@accept{pdftitle}{\hyxmp@alt@title}
\hyxmp@LA@accept{pdfsubject}{\hyxmp@alt@description}
\hyxmp@LA@accept{pdfcopyright}{\hyxmp@alt@rights}
%    \end{macrocode}
%
% \begin{macro}{\XMPLangAlt}
% Argument~|#1| is a language expressed as a two-letter country code and
% optional two-letter region code.  Argument~|#2| is a list of
% \meta{key}=\meta{value} pairs.  Keys correspond to |\hypersetup|
% options such as ``|pdftitle|'', ``|pdfsubject|'', and
% ``|pdfcopyright|''.  Values are the alternative-language form of the
% text provided for the corresponding option.
% \changes{v3.3}{2017/07/22}{Added this macro based on a request---and
%   some code---by Niklas Beisert to support metadata expressed in multiple
%   languages}
%    \begin{macrocode}
\newcommand{\XMPLangAlt}[2]{%
  \let\do=\relax
%    \end{macrocode}
% \begin{macro}{\hyxmp@cur@lang}
% Store the provided language, which will be used during option processing.
%    \begin{macrocode}
  \edef\hyxmp@cur@lang{#1}%
  \setkeys{hyxmp@LA}{#2}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsection{UUID generation}
% \label{sec:uuid-gen}
%
% We use a linear congruential generator to produce pseudorandom
% version~4 \acro{UUID}s~\cite{Leach2005:uuid}.  True, this method has
% its flaws but it's simple to implement in \tex\ and is good enough for
% producing the \acro{XMP} \xmpprop{xmpMM:DocumentID} and
% \xmpprop{xmpMM:InstanceID} fields.
%
% \begin{macro}{\hyxmp@modulo@a}
% Replace the contents of |\@hyxmp@count| with the contents modulo~|#1|.
% Note that |\@tempcntb| is overwritten in the process.
%    \begin{macrocode}
\def\hyxmp@modulo@a#1{%
  \@tempcntb=\@hyxmp@count
  \divide\@tempcntb by #1
  \multiply\@tempcntb by #1
  \advance\@hyxmp@count by -\@tempcntb
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@big@prime}
% \begin{macro}{\hyxmp@big@prime@ii}
% Define a couple of large prime numbers that can still be stored in a
% \tex\ counter.
%    \begin{macrocode}
\def\hyxmp@big@prime{536870923}
\def\hyxmp@big@prime@ii{536870027}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@seed@rng}
% \begin{macro}{\hyxmp@one@token}
% Seed \pkgname{hyperxmp}'s random-number generator from a given piece
% of text.
%    \begin{macrocode}
\def\hyxmp@seed@rng#1{%
  \@hyxmp@count=\hyxmp@big@prime
  \futurelet\hyxmp@one@token\hyxmp@seed@rng@i#1\@empty
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@seed@rng@i}
% \begin{macro}{\hyxmp@one@token}
% \begin{macro}{\next}
% Do all of the work for |\hyxmp@seed@rng|.  For each character code $c$
% of the input text, assign $\mathtt{\string\@hyxmp@count} \leftarrow 3
% \cdot \mathtt{\string\@hyxmp@count} + c
% \pmod{\mathtt{\string\hyxmp@big@prime}}$.
%    \begin{macrocode}
\def\hyxmp@seed@rng@i{%
  \ifx\hyxmp@one@token\@empty
    \let\next=\relax
  \else
    \def\next##1{%
      \multiply\@hyxmp@count by 3
      \advance\@hyxmp@count by `##1
      \hyxmp@modulo@a{\hyxmp@big@prime}%
      \futurelet\hyxmp@one@token\hyxmp@seed@rng@i
    }%
  \fi
  \next
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@set@rand@num}
% \begin{macro}{\hyxmp@rand@num}
% Advance |\hyxmp@rand@num| to the next pseudorandom number in the
% sequence.  Specifically, we assign $\mathtt{\string\hyxmp@rand@num}
% \leftarrow 3 \cdot \mathtt{\string\hyxmp@rand@num} +
% \mathtt{\string\hyxmp@big@prime@ii}
% \pmod{\mathtt{\string\hyxmp@big@prime}}$.  Note that both |\@hyxmp@count|
% and |\@tempcntb| are overwritten in the process.
%    \begin{macrocode}
\def\hyxmp@set@rand@num{%
  \@hyxmp@count=\hyxmp@rand@num
  \multiply\@hyxmp@count by 3
  \advance\@hyxmp@count by \hyxmp@big@prime@ii
  \hyxmp@modulo@a{\hyxmp@big@prime}%
  \xdef\hyxmp@rand@num{\the\@hyxmp@count}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@append@hex}
% Append a randomly selected hexadecimal digit to macro~|#1|.  Note that
% both |\@hyxmp@count| and |\@tempcntb| are overwritten in the process.
%    \begin{macrocode}
\def\hyxmp@append@hex#1{%
  \hyxmp@set@rand@num
  \@hyxmp@count=\hyxmp@rand@num
  \hyxmp@modulo@a{16}%
  \ifnum\@hyxmp@count<10
    \xdef#1{#1\the\@hyxmp@count}%
  \else
%    \end{macrocode}
% There \emph{must} be a better way to handle the numbers~10--15 than
% with |\ifcase|.
%    \begin{macrocode}
    \advance\@hyxmp@count by -10
    \ifcase\@hyxmp@count
      \xdef#1{#1a}%
      \or\xdef#1{#1b}%
      \or\xdef#1{#1c}%
      \or\xdef#1{#1d}%
      \or\xdef#1{#1e}%
      \or\xdef#1{#1f}%
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@append@hex@iii}
% Invoke |\hyxmp@append@hex| three times.
%    \begin{macrocode}
\def\hyxmp@append@hex@iii#1{%
  \hyxmp@append@hex#1%
  \hyxmp@append@hex#1%
  \hyxmp@append@hex#1%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@append@hex@iv}
% Invoke |\hyxmp@append@hex| four times.
%    \begin{macrocode}
\def\hyxmp@append@hex@iv#1{%
  \hyxmp@append@hex@iii#1%
  \hyxmp@append@hex#1%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@create@uuid}
% As per the definition of a version~4
% \acro{UUID}~\cite{Leach2005:uuid}, define macro~|#1| as a \acro{UUID}
% of the form
% ``|uuid:|\textit{xxxxxxxx}|-|\linebreak[0]\textit{xxxx}|-|\linebreak[0]\textit{4xxx}|-|\linebreak[0]\textit{yxxx}|-|\linebreak[0]\textit{xxxxxxxxxxxx}''
% in which each ``\textit{x}'' is a lowercase hexadecimal digit and
% ``\textit{y}'' is one of ``|8|'', ``|9|'', ``|a|'', or~``|b|''.  We
% assume that the random-number generator is already seeded.  Note that
% |\hyxmp@create@uuid| overwrites both |\@hyxmp@count| and |\@tempcntb|.
% \changes{v2.4}{2014/01/02}{Modified this macro to produce a proper
%   version~4 (random or pseudorandom) \protect\acro{UUID}}
%    \begin{macrocode}
\def\hyxmp@create@uuid#1{%
  \def#1{uuid:}%
  \hyxmp@append@hex@iv#1%
  \hyxmp@append@hex@iv#1%
  \g@addto@macro#1{-}%
  \hyxmp@append@hex@iv#1%
  \g@addto@macro#1{-4}%
  \hyxmp@append@hex@iii#1%
  \g@addto@macro#1{-}%
%    \end{macrocode}
% Randomly select one of ``|8|'', ``|9|'', ``|a|'', or~``|b|''.
%    \begin{macrocode}
  \hyxmp@set@rand@num
  \@hyxmp@count=\hyxmp@rand@num
  \hyxmp@modulo@a{4}%
  \ifcase\@hyxmp@count
    \g@addto@macro#1{8}%
    \or\g@addto@macro#1{9}%
    \or\g@addto@macro#1{a}%
    \or\g@addto@macro#1{b}%
  \fi
  \hyxmp@append@hex@iii#1%
  \g@addto@macro#1{-}%
  \hyxmp@append@hex@iv#1%
  \hyxmp@append@hex@iv#1%
  \hyxmp@append@hex@iv#1%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@def@DocumentID}
% \begin{macro}{\hyxmp@DocumentID}
% \begin{macro}{\hyxmp@seed@string}
% Seed the random-number generator with a function of the current
% filename, \acro{PDF} document title, and \acro{PDF} author, then invoke
% |\hyxmp@create@uuid| to define |\hyxmp@DocumentID| as a random \acro{UUID}.
% \changes{v3.4}{2017/11/04}{Correctly handle an author field of all spaces.
%   Bug reported by Ga\"etan Leurent}
%    \begin{macrocode}
\newcommand*{\hyxmp@def@DocumentID}{%
  \edef\hyxmp@seed@string{\hyxmp@jobname:\@pdftitle:\@pdfauthor:}%
  \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
  \edef\hyxmp@rand@num{\the\@hyxmp@count}%
  \hyxmp@create@uuid\hyxmp@DocumentID
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@def@InstanceID}
% \begin{macro}{\hyxmp@InstanceID}
% \begin{macro}{\hyxmp@seed@string}
% Seed the random-number generator with a function of the current
% filename, \acro{PDF} document title, \acro{PDF} author, and the
% current timestamp, then invoke |\hyxmp@create@uuid| to define
% |\hyxmp@InstanceID| as a random \acro{UUID}.  For the current
% timestamp, we use both the document-specified timestamp from
% \optname{pdfdate} and the \tex\ time.  The former can be more precise
% (to sub-seconds) but may be less random (as it depends on manual
% document modifications) while the latter is typically less precise (to
% minutes) but may be more random (as it is updated automatically).
% \changes{v3.5}{2018/11/27}{Seed with the \protect\TeX\ timestamp in
%   addition to the document-specified timestamp}
%    \begin{macrocode}
\newcommand*{\hyxmp@def@InstanceID}{%
  \hyxmp@today@xmp@define{\hyxmp@seed@string}%
  \edef\hyxmp@seed@string{%
    \hyxmp@jobname:\@pdftitle:\@pdfauthor:\hyxmp@today@xmp:\hyxmp@seed@string
  }%
  \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
  \edef\hyxmp@rand@num{\the\@hyxmp@count}%
  \hyxmp@create@uuid\hyxmp@InstanceID
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsection{Constructing the XMP packet}
%
% An \acro{XMP} packet ``shall consist of the following, in order: a
% header \acro{PI}, the serialized \acro{XMP} data model (the \acro{XMP}
% packet) with optional white-space padding, and a trailer
% \acro{PI}''~\cite{Adobe2012:XMP}.  (``\acro{PI}'' is an abbreviation for
% ``processing instructions'').  The serialized \acro{XMP} includes blocks
% of \acro{XML} for various \acro{XMP} schemata:
% ^^A
% \schema[Adobe PDF]{Adobe \protect\acro{PDF}} (Section~\ref{sec:adobe-pdf}),
% \schema{Dublin Core} (Section~\ref{sec:dublin-core}),
% \schema[XMP Rights Management]{\protect\acro{XMP} Rights Management} (Section~\ref{sec:xmp-rights}),
% \schema[XMP Media Management]{\protect\acro{XMP} Media Management} (Section~\ref{sec:xmp-media}),
% \schema[XMP Basic]{\protect\acro{XMP} Basic} (Section~\ref{sec:xmp-basic}),
% \schema{Photoshop} (Section~\ref{sec:photoshop}),
% \index{PDF/A Identification schema=\acro {PDF/A} Identification schema}
% \index{PDF/X Identification schema=\acro {PDF/X} Identification schema}
% \index{PDF/UA Identification schema=\acro {PDF/UA} Identification schema}
% \index{schemata&PDF/A Identification=\acro {PDF/A} Identification}
% \index{schemata&PDF/X Identification=\acro {PDF/X} Identification}
% \index{schemata&PDF/UA Identification=\acro {PDF/UA} Identification}
% \acro{PDF}\textsc{/*} Identification (Section~\ref{sec:pdfX-id}),
% \schema[IPTC Photo Metadata]{\protect\acro{IPTC} Photo Metadata} (Section~\ref{sec:photo-meta}),
% \schema[PRISM Basic Metadata]{\protect\acro{PRISM} Basic Metadata} (Section~\ref{sec:prism-meta}),
% \schema{Journal Article Versions} (Section~\ref{sec:niso-jav-meta}), and
% \schema[XMP Paged-Text]{\protect\acro{XMP} Paged-Text} (Section~\ref{sec:xmp-paged-text}).
% ^^A
% The |\hyxmp@construct@packet| macro
% (Section~\ref{sec:combining-schemata}) constructs the \acro{XMP} packet
% into |\hyxmp@xml|.  It first writes the appropriate \acro{XML} header,
% then calls the various schema-writing macros, then injects
% |\hyxmp@padding| as padding, and finally writes the appropriate
% \acro{XML} trailer.
%
% \subsubsection{XMP utility functions}
%
% \begin{macro}{\hyxmp@add@to@xml}
% Given a piece of text, replace all underscores with category-code~11
% (``other'') spaces and all |^C| characters with commas, then append
% the result to the |\hyxmp@xml| macro.
% \changes{v2.0}{2012/08/24}{Updated also to replace commas}
% \changes{v2.5}{2014/06/19}{Updated also to replace underscores and to
%   modify only the text being added, not the already-modified text}
% \changes{v2.8}{2014/04/05}{Corrected inadvertent lowercasing of non-Latin
%   characters when run under \XeLaTeX\ or \LuaLaTeX\ (bug reported by
%   Leonid Sinev)}
%    \begin{macrocode}
\newcommand*{\hyxmp@add@to@xml}[1]{%
  \bgroup
    \@hyxmp@count=0
    \ifhyxmp@unicodetex
      \@tempcntb=65536%
    \else
      \@tempcntb=256%
    \fi
    \loop
      \lccode\@hyxmp@count=\@hyxmp@count
      \advance\@hyxmp@count by 1
      \ifnum\@hyxmp@count<\@tempcntb
    \repeat
    \lccode`\_=`\ \relax
    \lccode`\^^C=`\,\relax
    \lccode`\^^U=`\_\relax
    \lowercase{\xdef\hyxmp@new@xml{#1}}%
    \xdef\hyxmp@xml{\hyxmp@xml\hyxmp@new@xml}%
  \egroup
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@hash}
% Define a category-code~11 (``other'') version of the ``|#|'' character.
%    \begin{macrocode}
\bgroup
\catcode`\#=11
\gdef\hyxmp@hash{#}
\egroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@padding}
% \begin{macro}{\hyxmp@xml}
% The \acro{XMP} specification recommends leaving approximately
% 2000~bytes of whitespace at the end of each \acro{XMP} packet to
% facilitate editing the packet in place~\cite{Adobe2012:XMP}.
% |\hyxmp@padding| is defined to contain 32~lines of 63~spaces and a
% newline apiece for a total of 2048 characters of whitespace.
%    \begin{macrocode}
\bgroup
  \xdef\hyxmp@xml{}%
  \hyxmp@add@to@xml{%
_______________________________________________________________^^J%
  }
  \xdef\hyxmp@padding{\hyxmp@xml}%
\egroup
\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@x@default}
% Define an \xmpterm{x-default} string that we can use in comparisons
% with |\@pdfmetalang|.
%    \begin{macrocode}
\newcommand*{\hyxmp@x@default}{x-default}
%    \end{macrocode}
% \end{macro}
%
%
% \subsubsection{The Adobe PDF schema}
% \label{sec:adobe-pdf}
%
% \begin{schemadesc}[Adobe PDF]{Adobe \protect\acro{PDF}}
%
% Older versions of \pkgname{hyperref} defined a default producer; newer
% versions do not.  Instead, they let the \tex\ engine define the
% producer itself.  This poses a problem for \acro{PDF/A} compliance
% because \pkgname{hyperxmp} sees an empty producer and therefore omits
% writing a \xmpprop{pdf:Producer} to the \acro{XMP} packet, causing a
% mismatch between the data in the \acro{XMP} packet and the data in the
% \acro{PDF} \pdfterm{Info} dictionary.  To ensure consistency between
% \acro{XMP} and \pdfterm{Info}, we explicitly define our own default
% |\@pdfproducer| here.
%
% \begin{macro}{\@pdfproducer}
% \begin{macro}{\hyxmp@define@pdfproducer}
% Define |\@pdfproducer| using the banner string if available or the
% \tex\ engine's version number if not.
% \changes{v5.0}{2020/03/01}{Added this macro}
% \changes{v5.1}{2020/04/06}{Check for \string\LuaTeX\ before checking for
%   \string\pdfTeX\ to work around \string\pkgname{luatex85}'s confusing
%   \string\pkgname{iftex} by defining \string\cs{pdftexversion}.  Thanks
%   to Robin Schwab for the bug report}
%    \begin{macrocode}
\newcommand*{\hyxmp@define@pdfproducer}{%
  \gdef\@pdfproducer{TeX}
  \ifLuaTeX
    \expandafter\hyxmp@banner@to@producer\expandafter{\luatexbanner}%
  \else
    \ifPDFTeX
      \expandafter\hyxmp@banner@to@producer\expandafter{\pdftexbanner}%
    \else
      \ifXeTeX
        \edef\@pdfproducer{XeTeX version \the\XeTeXversion\XeTeXrevision}%
      \fi
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfproducer}
% \begin{macro}{\hyxmp@banner@to@producer}
% Define |\@pdfproducer| as the \tex\ engine's banner string
% \ifPDFTeX
% (e.g.,~``\texttt{\pdftexbanner}''),
% \else
%   \ifLuaTeX
%     (e.g.,~``\texttt{\luatexbanner}''),
%   \else
%     (e.g.,~``\texttt{This is pdfTeX, Version 3.14159265-2.6-1.40.20
%     (TeX Live 2019/Debian) kpathsea version 6.3.1}''),
%   \fi
% \fi
% removing the initial ``\texttt{This is}'' if possible (specifically,
% when $\varepsilon$-\TeX's\index{e-TeX=$\varepsilon$-\TeX}
% |\scantokens| primitive is available).
% \changes{v5.1}{2020/04/03}{Prevent the category code of ``@'' from
%   propagating past the \cs{begin}\string\texttt{\{document\}}.
%   Thanks to Robert Schlicht for noticing this catcode ``leak'' and
%   providing a correction}
%    \begin{macrocode}
\def\hyxmp@banner@to@producer#1{%
  \ifx\scantokens\relax
    \gdef\@pdfproducer{#1}%
  \else
    {\scantokens{\makeatletter\hyxmp@remove@this#1\relax}}%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@pdfproducer}
% \begin{macro}{\hyxmp@remove@this}
% Define |\@pdfproducer| as a given banner string with the initial
% ``\texttt{This is}'' stripped off the beginning.
%    \begin{macrocode}
\def\hyxmp@remove@this This is #1\relax{\gdef\@pdfproducer{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% If \optname{pdfproducer} wasn't specified and \pkgname{hyperref}
% didn't already define |\@pdfproducer|---old versions of
% \pkgname{hyperref} did; newer ones don't---try to assign a meaningful
% producer string and use that.
% \changes{v5.0}{2020/03/02}{Define a default producer}
%    \begin{macrocode}
\AtBeginDocument{%
  \ifx\@pdfproducer\relax
    \hyxmp@define@pdfproducer
  \fi
}
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@assign@major@minor}
% Assign |\hyxmp@major@minor| to be the \acro{PDF} version targeted by
% the running \TeX\ engine.
% \changes{v5.2}{2020/05/10}{Added this macro.  \string\pkgname{hyperxmp}
%   now correctly specifies \string\xmpprop{pdf:PDFVersion} when
%   generating \string\acro{PDF}~2.0+.  Thanks to Ulrike Fischer for
%   alerting me to \string\acro{PDF}~2.0's availability in the
%   \string\TeX\ ecosystem and informing me how to activate it}
% \begin{macro}{\hyxmp@major@minor}
%    \begin{macrocode}
\newcommand*{\hyxmp@assign@major@minor}{%
  \@ifundefined{pdfvariable}{%
    \@ifundefined{pdfminorversion}{%
%    \end{macrocode}
% Case 1: Neither |\pdfvariable| nor |\pdfminorversion| is defined
% (\XeLaTeX\ and regular \LaTeX).
%    \begin{macrocode}
    }{%
%    \end{macrocode}
% Case 2: |\pdfminorversion| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
%    \begin{macrocode}
      \xdef\hyxmp@major@minor{\the\pdfminorversion}%
      \@ifundefined{pdfmajorversion}{%
%    \end{macrocode}
% Case 2(a): |\pdfmajorversion| is not defined (older versions of
% \pdfLaTeX\ and \LuaLaTeX).
%    \begin{macrocode}
        \xdef\hyxmp@major@minor{1.\hyxmp@major@minor}%
      }{%
%    \end{macrocode}
% Case 2(b): |\pdfmajorversion| is defined (\pdfLaTeX~1.40.21+).
%    \begin{macrocode}
        \xdef\hyxmp@major@minor{\the\pdfmajorversion.\hyxmp@major@minor}%
      }%
    }%
  }{%
%    \end{macrocode}
% Case 3: |\pdfvariable| is defined (\LuaLaTeX~0.85+).
%    \begin{macrocode}
    \xdef\hyxmp@major@minor{\the\pdfvariable majorversion.\the\pdfvariable minorversion}%
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdf@schema}
% Add properties defined by the Adobe \acro{PDF} schema to the |\hyxmp@xml|
% macro.
%    \begin{macrocode}
\newcommand*{\hyxmp@pdf@schema}{%
%    \end{macrocode}
% Add a block of \acro{XML} to |\hyxmp@xml| that lists the document's
% keywords (the \xmpprop{pdf:Keywords} property), the tools used to
% produce the \acro{PDF} file (the \xmpprop{pdf:Producer} property), and
% the version of the \acro{PDF} standard adhered to (the
% \xmpprop{pdf:PDFVersion} property).  Unlike most of the other schemata
% that \pkgname{hyperxmp} supports, the Adobe \acro{PDF} schema is
% \emph{always} included in the document, even if all of its keys are
% empty.  This is because \PDFstd{A}{1}{b}{} requires the keywords and
% producer to be the same in the \acro{XMP} metadata and the \acro{PDF}
% metadata.  Because \pkgname{hyperref} always specifies the
% \pdfterm{Keywords} and \pdfterm{Producer} fields, even when they're
% empty, \pkgname{hyperxmp} has to follow suit and define
% \xmpprop{pdf:Keywords} and \xmpprop{pdf:Producer} in the \acro{XMP}
% packet.
% \changes{v2.4}{2013/12/21}{Made
%   \texttt{\string\string\string\hyxmp@pdf@schema}
%   \protect\emph{always} include the Adobe \protect\acro{PDF} schema,
%   even when empty.  Florian Breitwieser noted that this is necessary
%   for \protect\PDFstd{A}{1}{b}{} compliance}
% \changes{v5.0}{2020/02/28}{Honor \protect\optname{pdftrapped}}
%    \begin{macrocode}
  \hyxmp@add@simple@var{pdf:Producer}{@pdfproducer}%
  \hyxmp@add@simple@var{pdf:Keywords}{@pdfkeywords}%
  \hyxmp@add@simple{pdf:Trapped}{\@pdftrapped}%
  \hyxmp@assign@major@minor
  \hyxmp@add@simple@var{pdf:PDFVersion}{hyxmp@major@minor}%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The Dublin Core schema}
% \label{sec:dublin-core}
%
% \begin{schemadesc}{Dublin Core}
%
% \begin{macro}{\ifhyxmp@multi@langs}
% \begin{macro}{\hyxmp@multi@langstrue}
% \begin{macro}{\hyxmp@multi@langsfalse}
% These macros are used locally to \cs{hyxmp@rdf@dc}.  If the property
% being processed has values in different languages,
% \cs{ifhyxmp@multi@langs} evaluates to \textsc{true}.  If it has a
% value in only a single language, \cs{ifhyxmp@multi@langs} evaluates to
% \textsc{false}.
%    \begin{macrocode}
\newif\ifhyxmp@multi@langs
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@rdf@dc}
% Given an optional |\if|\meta{something} statement (|#1|), a Dublin Core
% property~(|#2|) and a macro containing some |\pdfstringdef|-defined
% text~(|#3|), append the appropriate block of \acro{XML} to the |\hyxmp@xml|
% macro.
% \changes{v1.4}{2011/06/12}{Included metadata in the \xmpterm{x-default}
%   language regardless of the specified metadata language}
% \changes{v3.3}{2017/07/22}{Bug fix: Output the metadata language as
%   correct \noexpand\acro{XML} even when \noexpand\pkgname{hyperref} is
%   loaded with the \noexpand\optname{unicode} option}
% \changes{v5.5}{2020/07/17}{List \protect\xmpterm{x-default} alternatives
%   before language-specific alternatives, as dictated by the
%   \protect\acro{XMP} specification~\protect\cite{Adobe2012:XMP}}
% \changes{v5.5}{2020/07/21}{Rewrite the core part of this macro to
%   divide it into four, cleanly defined cases}
%    \begin{macrocode}
\newcommand*{\hyxmp@rdf@dc}[3][\iffalse]{%
%    \end{macrocode}
% Set |\@tempswatrue| only if the given text is nonempty or the provided
% conditional evaluates to \textsc{true}.
%    \begin{macrocode}
  \@ifmtargexp{#3}{\@tempswafalse}{\@tempswatrue}%
  #1
    \@tempswatrue
  \fi
%    \end{macrocode}
% Append the corresponding \acro{XML} only if |\@tempswatrue|.
%    \begin{macrocode}
  \if@tempswa
    \hyxmp@xmlify{#3}%
%    \end{macrocode}
% \begin{macro}{\hyxmp@value}
% Store the \acro{XML}-ified version of |#3| in |\hyxmp@value| so we can
% reuse |\hyxmp@xmlifiied| if necessary.
%    \begin{macrocode}
    \let\hyxmp@value=\hyxmp@xmlified
    \hyxmp@add@to@xml{%
______<dc:#2>^^J%
________<rdf:Alt>^^J%
    }%
%    \end{macrocode}
% Record whether property~|#2| has definitions in multiple languages.
%    \begin{macrocode}
    \@if@def@and@nonempty{hyxmp@alt@#2}{%
      \hyxmp@multi@langstrue
    }{%
      \hyxmp@multi@langsfalse
    }%
%    \end{macrocode}
% There are now four cases to consider: the cross product of
% \{\optname{pdfmetalang}~$=$ ``\xmpterm{x-default}'',
% \optname{pdfmetalang}~$\neq$ ``\xmpterm{x-default}''\} and
% \{\cs{XMPLangAlt} was specified, \cs{XMPLangAlt} was not specified\}.
% We handle each of these in turn.
%    \begin{macrocode}
    \ifx\@pdfmetalang\hyxmp@x@default
      \ifhyxmp@multi@langs
%    \end{macrocode}
% \textbf{Case~1}: No \optname{pdfmetalang} but \cs{XMPLangAlt}.
% We consider this an error because the \xmpterm{x-default} language will
% not have a matching non-default language, in violation of the
% \acro{XMP} specification's guidance~\cite[p.~23]{Adobe2012:XMP}:
%
% \begin{quote}
%   \sffamily
%
%   An \textbf{xml:lang} value of ``x-default'' may be used to
%   explicitly denote a default item.  If used, the ``x-default'' item
%   shall be first in the array and its simple text value should be
%   repeated in another item in which \textbf{xml:lang} specifies its
%   actual language.  However, an ``x-default'' item may be the only
%   item, in which case there is only a default value in no defined
%   language.
% \end{quote}
%    \begin{macrocode}
        \PackageError{hyperxmp}%
          {\string\XMPLangAlt\space was used without specifying
           pdfmetalang\MessageBreak
           or pdflang}%
          {Be sure to assign a language code to the pdfmetalang key and/or a
           document\MessageBreak
           language to the pdflang key (e.g., \string\hypersetup{pdfmetalang={en}}).}%
      \else
%    \end{macrocode}
% \textbf{Case~2}: No \optname{pdfmetalang} and no \cs{XMPLangAlt}.
% Here we specify only \xmpterm{x-default} as the language, as per the
% guidance quoted above.
%    \begin{macrocode}
        \hyxmp@add@to@xml{%
__________<rdf:li xml:lang="\hyxmp@x@default">\hyxmp@value</rdf:li>^^J%
        }%
      \fi
    \else
      \ifhyxmp@multi@langs
%    \end{macrocode}
% \textbf{Case~3}: Both \optname{pdfmetalang} and \cs{XMPLangAlt}.  In
% this case, we include an \xmpterm{x-default} followed by the
% \optname{pdfmetalang} language, followed by all of the language
% alternatives.
%    \begin{macrocode}
        \hyxmp@xmlify{\@pdfmetalang}%
        \hyxmp@add@to@xml{%
__________<rdf:li xml:lang="\hyxmp@x@default">\hyxmp@value</rdf:li>^^J%
__________<rdf:li xml:lang="\hyxmp@xmlified">\hyxmp@value</rdf:li>^^J%
        }%
        \def\do##1##2{
          \hyxmp@xmlify{##2}%
          \hyxmp@add@to@xml{%
    __________<rdf:li xml:lang="##1">\hyxmp@xmlified</rdf:li>^^J%
          }%
        }%
        \csname hyxmp@alt@#2\endcsname
      \else
%    \end{macrocode}
% \textbf{Case~4}: \optname{pdfmetalang} but no \cs{XMPLangAlt}.  To
% reduce redundancy we omit the \xmpterm{x-default} and include the
% single language in which the text appears.
%    \begin{macrocode}
        \hyxmp@xmlify{\@pdfmetalang}%
        \hyxmp@add@to@xml{%
__________<rdf:li xml:lang="\hyxmp@xmlified">\hyxmp@value</rdf:li>^^J%
        }%
      \fi
    \fi
%    \end{macrocode}
% Complete this \acro{XMP} element.
%    \begin{macrocode}
    \hyxmp@add@to@xml{%
________</rdf:Alt>^^J%
______</dc:#2>^^J%
    }%
  \fi
}%
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@list@to@xml}
% Given an optional |\if|\meta{something} statement (|#1|), a Dublin Core
% property~(|#2|), an \acro{RDF} array~(|#3|), and a macro containing a
% comma-separated list~(|#4|), append the appropriate block of \acro{XML} to
% the |\hyxmp@xml| macro.
% \changes{v2.0}{2012/08/02}{Modified by Heiko Oberdiek to use the new
%   \term{Unicode}-processing macros}
%    \begin{macrocode}
\newcommand*{\hyxmp@list@to@xml}[4][\iffalse]{%
%    \end{macrocode}
% Set |\@tempswatrue| only if the given list is nonempty or the provided
% conditional evaluates to \textsc{true}.
%    \begin{macrocode}
  \@ifmtargexp{#4}{\@tempswafalse}{\@tempswatrue}%
  #1
    \@tempswatrue
  \fi
%    \end{macrocode}
% Append the corresponding \acro{XML} only if |\@tempswatrue|.
%    \begin{macrocode}
  \if@tempswa
    \hyxmp@add@to@xml{%
______<dc:#2>^^J%
________<rdf:#3>^^J%
    }%
    \bgroup
%    \end{macrocode}
% \begin{macro}{\@elt}
% Re-encode the text from \term{Unicode} if necessary.  Then redefine
% |\@elt| to \acro{XML}-ify each element of the list and append it to
% |\hyxmp@xmlified|.
%    \begin{macrocode}
      \hyxmp@xmlify{#4}%
      \hyxmp@commas@to@list\hyxmp@list{\hyxmp@xmlified}%
      \def\@elt##1{%
        \hyxmp@add@to@xml{%
__________<rdf:li>##1</rdf:li>^^J%
        }%
      }%
      \hyxmp@list
    \egroup
    \hyxmp@add@to@xml{%
________</rdf:#3>^^J%
______</dc:#2>^^J%
    }%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@singleton@dc}
% Given an optional list type (|Seq| or |Bag|), a Dublin Core property,
% and a string, append a block of \acro{XML} representing a one-element
% list consisting of the given string.
% \changes{v4.1}{2019/04/05}{Added this macro}
%    \begin{macrocode}
\newcommand{\hyxmp@singleton@dc}[3][Bag]{%
  \@ifnotmtargexp{#3}{%
    \hyxmp@xmlify{#3}%
    \hyxmp@add@to@xml{%
______<dc:#2>^^J%
________<rdf:#1>^^J%
__________<rdf:li>\hyxmp@xmlified</rdf:li>^^J%
________</rdf:#1>^^J%
______</dc:#2>^^J%
    }%
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@cond@dc@identifier}
% Conditionally add a \xmpprop{dc:identifier} tag.  Given a prefix
% string~(|#1|) and a main string~(|#2|), wrap these in a
% \xmpprop{dc:identifier} if the main string is nonempty and
% |\hyxmp@xmlified| \emph{is} empty (implying the
% \xmpprop{dc:identifier} has not yet been written).
% \changes{v5.2}{2020/04/29}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@cond@dc@identifier}[2]{%
  \ifx\hyxmp@xmlified\@empty
    \@ifnotmtargexp{#2}{%
      \hyxmp@add@simple@pfx{dc:identifier}{#1}{#2}%
    }%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@dc@schema}
% Add properties defined by the Dublin Core schema to the |\hyxmp@xml|
% macro.  Specifically, we add entries for the \xmpprop{dc:title}
% property if the author specified a \optname{pdftitle}, the
% \xmpprop{dc:description} property if the author specified a
% \optname{pdfsubject}, the \xmpprop{dc:rights} property if the author
% specified a \optname{pdfcopyright}, the \xmpprop{dc:creator} property
% if the author specified a \optname{pdfauthor}, the
% \xmpprop{dc:subject} property if the author specified
% \optname{pdfkeywords}, the \xmpprop{dc:language} property if the
% author specified \optname{pdflang}, the \xmpprop{dc:type} property if
% the author specified \optname{pdftype}, and the
% \xmpprop{dc:identifier} if the author specified
% \optname{pdfidentifier} or if we can derive it from other options.  We
% also specify the \xmpprop{dc:source} property using the base name of
% the source file with |.tex| appended and the \xmpprop{dc:date}
% property using the date the document was run through \LaTeX---unless
% the author specified \optname{pdfdate}, in which case we use that.
% \changes{v2.0}{2012/08/26}{Added support for \xmpprop{dc:language}
%   and \xmpprop{dc:source}}
% \changes{v2.4}{2013/12/21}{Made \xmpprop{dc:language} a \xmpterm{Bag}
%   instead of an individual item so as to conform to the latest
%   \acro{XMP} specifications, a detail identified by Florian Breitwieser}
% \changes{v5.3}{2020/06/13}{Include all languages used in the document
%   in \protect\xmpprop{dc:language}}
% \changes{v5.4}{2020/06/18}{Bug fix: Use \protect\cs{hyxmp@today@xmp}
%   as the date only if \protect\cs{@pdfdatetime} is undefined}
%    \begin{macrocode}
\newcommand*{\hyxmp@dc@schema}{%
  \hyxmp@add@simple{dc:format}{application/pdf}%
  \hyxmp@rdf@dc[\ifHy@pdfa]{title}{\@pdftitle}%
  \hyxmp@rdf@dc[\ifHy@pdfa]{description}{\@pdfsubject}%
  \hyxmp@rdf@dc{rights}{\@pdfcopyright}%
  \hyxmp@singleton@dc{publisher}{\@pdfpublisher}%
  \@ifmtargexp{\@pdfdatetime}{%
    \hyxmp@singleton@dc[Seq]{date}{\hyxmp@today@xmp}%
  }{%
    \hyxmp@singleton@dc[Seq]{date}{\@pdfdatetime}%
  }%
  \hyxmp@singleton@dc{type}{\@pdftype}%
  \hyxmp@list@to@xml[\ifHy@pdfa]{creator}{Seq}{\hyxmp@pdfauthor}%
  \hyxmp@list@to@xml{subject}{Bag}{\hyxmp@pdfkeywords}%
  \ifx\@pdfsource\@empty
  \else
    \hyxmp@add@simple{dc:source}{\@pdfsource}%
  \fi
  \hyxmp@list@to@xml{language}{Bag}{\hyxmp@dc@lang}%
% If |\@pdfidentifier| is empty, try setting it to each of |\@pdfdoi|,
% |\@pdfeissn|, |\@pdfissn|, and |\@pdfisbn|, in turn, with proper
% syntactic adjustments.
%    \begin{macrocode}
  \@ifmtargexp{\@pdfidentifier}{%
    \let\hyxmp@xmlified=\@empty
    \hyxmp@cond@dc@identifier{info:doi/}{\@pdfdoi}%
    \hyxmp@cond@dc@identifier{urn:ISSN:}{\@pdfeissn}%
    \hyxmp@cond@dc@identifier{urn:ISSN:}{\@pdfissn}%
    \hyxmp@cond@dc@identifier{urn:ISBN:}{\@pdfisbn}%
  }{%
    \hyxmp@add@simple{dc:identifier}{\@pdfidentifier}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The XMP Rights Management schema}
% \label{sec:xmp-rights}
%
% \begin{schemadesc}[XMP Rights Management]{\protect\acro{XMP} Rights Management}
%
% \begin{macro}{\hyxmp@xmpRights@schema}
% Add properties defined by the \acro{XMP} Rights Management schema to the
% |\hyxmp@xml| macro.  Currently, these are only the
% \xmpprop{xmpRights:Marked} property and the
% \xmpprop{xmpRights:WebStatement} property.  If the author specified a
% copyright statement we mark the document as copyrighted.  If the
% author specified a license statement we include the \acro{URL} in the
% metadata.
% \changes{v1.4}{2011/05/29}{Renamed the \texttt{xapRights} namespace
%   prefix to \texttt{xmpRights}}
% \changes{v2.0}{2012/08/25}{Modified to include
%   \xmpprop{xmpRights:Marked} only when \optname{pdfcopyright} is
%   specified and \xmpprop{xmpRights:WebStatement} only when
%   \optname{pdflicenseurl} is specified}
%    \begin{macrocode}
\newcommand*{\hyxmp@xmpRights@schema}{%
%    \end{macrocode}
% \begin{macro}{\hyxmp@legal}
% Set |\hyxmp@rights| to |YES| if either \optname{pdfcopyright} or
% \optname{pdflicenseurl} was specified.
%    \begin{macrocode}
  \let\hyxmp@rights=\@empty
  \ifx\@pdflicenseurl\@empty
  \else
    \def\hyxmp@rights{YES}%
  \fi
  \ifx\@pdfcopyright\@empty
  \else
    \def\hyxmp@rights{YES}%
  \fi
%    \end{macrocode}
% Include the license-statement \acro{URL} and/or the copyright
% indication.  The copyright statement itself is included by
% |\hyxmp@dc@schema| in Section~\ref{sec:dublin-core}.
%    \begin{macrocode}
  \ifx\hyxmp@rights\@empty
  \else
    \ifx\@pdfcopyright\@empty
    \else
      \hyxmp@add@simple{xmpRights:Marked}{True}%
    \fi
    \hyxmp@add@simple{xmpRights:WebStatement}{\@pdflicenseurl}%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The XMP Media Management schema}
% \label{sec:xmp-media}
%
% \begin{schemadesc}[XMP Media Management]{\protect\acro{XMP} Media Management}
%
% \begin{macro}{\hyxmp@aep@toks}
% Once we reach the end of the preamble and know that \cs{@pdftitle} and
% \cs{@pdfauthor} are no longer expected to change we use those macros
% (and others) to define one \acro{UUID} for the document
% (\cs{hyxmp@DocumentID}) and one for the document instance
% (\cs{hyxmp@InstanceID}).  As explained in
% Section~\ref{sec:initial-prep}, we defer the invocation of
% \cs{AtEndPreamble} to the end of the file.
% \changes{v5.7}{2020/10/13}{As requested by Moritz Heckscher, define
%   \protect\cs{hyxmp@DocumentID} and \protect\cs{hyxmp@InstanceID} at
%   the end of the preamble instead of at the end of the document}
%    \begin{macrocode}
\expandafter\hyxmp@aep@toks\expandafter=\expandafter{%
  \the\hyxmp@aep@toks
  \AtEndPreamble{%
    \@ifmtargexp{\hyxmp@DocumentID}{\hyxmp@def@DocumentID}{}%
    \@ifmtargexp{\hyxmp@InstanceID}{\hyxmp@def@InstanceID}{}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@mm@schema}
% Add properties defined by the \acro{XMP} Media Management schema to
% the |\hyxmp@xml| macro.  According to the \acro{XMP} specification,
% the \xmpprop{xmpMM:DocumentID} property is supposed to uniquely
% identify a document, and the \xmpprop{xmpMM:InstanceID} property is
% supposed to change with each save operation~\cite{Adobe2012:XMP}.  As
% seen in Section~\ref{sec:uuid-gen}, we do what we can to honor this
% intention from within a \tex-based workflow.  We additionally support
% the \xmpprop{xmpMM:VersionID} property, whose value is supplied by
% the author using \optname{pdfversionid}.
% \changes{v1.4}{2011/05/29}{Renamed the \texttt{xapMM} namespace
%   prefix to \texttt{xmpMM}}
% \changes{v3.5}{2018/11/27}{Generate \protect\cs{hyxmp@DocumentID} and
%   \protect\cs{hyxmp@InstanceID} only if the document does not already
%   define these using the \protect\optname{pdfdocumentid} and
%   \protect\optname{pdfinstanceid} options}
% \changes{v4.0}{2019/03/09}{Include \protect\xmpprop{xmpMM:VersionID} in
%   the \protect\acro{XMP} packet}
%    \begin{macrocode}
\gdef\hyxmp@mm@schema{%
  \hyxmp@add@simple{xmpMM:DocumentID}{\hyxmp@DocumentID}%
  \hyxmp@add@simple{xmpMM:InstanceID}{\hyxmp@InstanceID}%
  \hyxmp@add@simple{xmpMM:VersionID}{\@pdfversionid}%
  \hyxmp@add@simple{xmpMM:RenditionClass}{\@pdfrendition}%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The XMP Basic schema}
% \label{sec:xmp-basic}
%
% \begin{schemadesc}[XMP Basic]{\protect\acro{XMP} Basic}

% \begin{macro}{\hyxmp@xmp@basic@schema}
% Add properties defined by the \acro{XMP} Basic schema to the
% |\hyxmp@xml| macro.  These include a bunch of dates (all set to the
% same value) and the base \acro{URL} for the document if specified with
% \optname{baseurl}.
% \changes{v2.0}{2012/08/26}{Added this macro}
% \changes{v3.0}{2016/07/04}{Made the \protect\acro{XMP}
%   \protect\xmpprop{xmp:CreateDate}, \protect\xmpprop{xmp:ModifyDate},
%   and \protect\xmpprop{xmp:MetadataDate} match the \protect\acro{PDF}
%   \protect\pdfterm{CreationDate}}
% \changes{v3.2}{2017/01/22}{Honor \string\pkgname{hyperref}'s
%   \string\optname{pdfcreationdate} and \string\optname{pdfmoddate}
%   options plus a new \string\optname{pdfmetadate} option.  Leonid
%   Sinev requested this additional control and helped test the resulting
%   \protect\pkgname{hyperxmp} code}
%    \begin{macrocode}
\newcommand*{\hyxmp@xmp@basic@schema}{%
%    \end{macrocode}
% For the document's creation date, use the user-specified
% |\@pdfcreationdate| if defined and non-empty.  Otherwise use our
% fabricated |\hyxmp@today@xmp|.
%    \begin{macrocode}
  \@ifmtargexp{\@pdfcreationdate}{%
    \hyxmp@add@simple{xmp:CreateDate}{\hyxmp@today@xmp}%
  }{%
    \hyxmp@add@simple{xmp:CreateDate}{%
      \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfcreationdate}}%
  }%
%    \end{macrocode}
% For the document's modification date, use the user-specified
% |\@pdfmoddate| if defined and non-empty.  Otherwise use our
% fabricated |\hyxmp@today@xmp|.
%    \begin{macrocode}
  \@ifmtargexp{\@pdfmoddate}{%
    \hyxmp@add@simple{xmp:ModifyDate}{\hyxmp@today@xmp}%
  }{%
    \hyxmp@add@simple{xmp:ModifyDate}{%
      \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfmoddate}}%
  }%
%    \end{macrocode}
% For the document's metadata date, use the user-specified
% |\@pdfmetadatetime| if defined and non-empty.  Otherwise use our
% fabricated |\hyxmp@today@xmp|.
%    \begin{macrocode}
  \@ifmtargexp{\@pdfmetadatetime}{%
    \hyxmp@add@simple{xmp:MetadataDate}{\hyxmp@today@xmp}%
  }{%
    \hyxmp@add@simple{xmp:MetadataDate}{\@pdfmetadatetime}%
  }%
%    \end{macrocode}
% Define the creation tool and the base \acro{URL}.
%    \begin{macrocode}
  \hyxmp@add@simple{xmp:CreatorTool}{\@pdfcreator}%
  \hyxmp@add@simple{xmp:BaseURL}{\@baseurl}%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The Photoshop schema}
% \label{sec:photoshop}
%
% \begin{schemadesc}{Photoshop}
%
% \begin{macro}{\hyxmp@photoshop@schema}
% \changes{v2.0}{2012/08/26}{Simplified using
%   \texttt{\string\string\string\hyxmp@add@simple}}
% \begin{macro}{\hyxmp@photoshop@data}
% Add properties defined by the Photoshop schema to the |\hyxmp@xml|
% macro.  We currently support only the
% \xmpprop{photoshop:AuthorsPosition} and
% \xmpprop{photoshop:CaptionWriter} properties.
%    \begin{macrocode}
\gdef\hyxmp@photoshop@schema{%
  \edef\hyxmp@photoshop@data{\@pdfauthortitle\@pdfcaptionwriter}%
  \hyxmp@add@simple{photoshop:AuthorsPosition}{\@pdfauthortitle}%
  \hyxmp@add@simple{photoshop:CaptionWriter}{\@pdfcaptionwriter}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{PDF/* Identification schemata}
% \label{sec:pdfX-id}
%
% \begin{schemadesc}[PDF/A Identification]{\protect\acro{PDF/A} Identification}
% \begin{schemadesc}[PDF/X Identification]{\protect\acro{PDF/X} Identification}
% \begin{schemadesc}[PDF/UA Identification]{\protect\acro{PDF/UA} Identification}
%
% \begin{macro}{\hyxmp@pdfa@id@schema}
% Add properties defined by the \acro{PDF/A} Identification
% schema~\cite{PDFA2008:xmp-props} to the |\hyxmp@xml| macro.  These
% properties identify a document as conforming to a particular
% \acro{PDF/A} standard.  We default to \PDFstd{A}{1}{b}{} if any
% \acro{PDF/A} compliance is detected but let the author override the
% ``1'' with \optname{pdfapart} and the ``b'' with
% \optname{pdfaconformance}.
% \changes{v2.4}{2013/12/21}{Added this macro}
% \changes{v2.9}{2016/04/12}{Let the author specify the \protect\acro{PDF/A}
%   part and conformance IDs, as requested by Leonid Sinev}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfa@id@schema}{%
  \ifHy@pdfa
    \hyxmp@add@simple{pdfaid:part}{\@pdfapart}%
    \hyxmp@add@simple{pdfaid:conformance}{\@pdfaconformance}%
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfua@id@schema}
% If the document conforms to a \acro{PDF/UA} standard, the author can
% indicate the standard version with \optname{pdfuapart}.
% \changes{v5.0}{2020/02/16}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfua@id@schema}{%
  \hyxmp@add@simple{pdfuaid:part}{\@pdfuapart}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfx@id@schema}
% \label{page:pdfx-id-schema}
% If the document conforms to a \acro{PDF/X} standard, the author can
% indicate the standard version with \optname{pdfxstandard}.  We
% separately handle \PDFstd{X}{1}{}{}, \PDFstd{X}{2}{}{} and
% \PDFstd{X}{3}{}{}, and \PDFstd{X}{4}{}{} onwards.
% \changes{v5.0}{2020/02/26}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfx@id@schema}{%
  \@hyxmp@count=0\hyxmp@pdfx@major\relax
  \ifnum\@hyxmp@count=0
  \else
    \ifnum\@hyxmp@count=1
      \hyxmp@add@simple{pdfx:GTS_PDFXVersion}{PDF/X-1:2001}%
      \hyxmp@add@simple{pdfx:GTS_PDFXConformance}{\@pdfxstandard}%
    \else
      \ifnum\@hyxmp@count<4
        \hyxmp@add@simple{pdfx:GTS_PDFXVersion}{\@pdfxstandard}%
      \else
        \hyxmp@add@simple{pdfxid:GTS_PDFXVersion}{\@pdfxstandard}%
      \fi
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
% \end{schemadesc}
% \end{schemadesc}
%
%
% \subsubsection{The IPTC Photo Metadata schema}
% \label{sec:photo-meta}
%
% \begin{schemadesc}[IPTC Photo Metadata]{\protect\acro{IPTC} Photo Metadata}
%
% \begin{macro}{\xmplinesep}
% Lines in multiline fields are separated by |\xmplinesep| in the
% generated \acro{XML}.  This defaults to an \acro{LF} (|^^J|) character
% but written as an \acro{XML} character entity for consistency across
% operating systems.
% \changes{v2.2}{2012/12/07}{Added this macro}
%    \begin{macrocode}
\begingroup
  \catcode`\&=12
  \catcode`\#=12
  \gdef\xmplinesep{&#xA;}
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@list@to@lines}
% Given a property~(|#1|) and a macro containing a comma-separated
% list~(|#2|), replace commas with |\xmplinesep|.  Do nothing if the
% list is empty.
% \changes{v2.2}{2012/12/07}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@list@to@lines}[2]{%
  \@ifnotmtargexp{#2}{%
    \bgroup
      \hyxmp@add@to@xml{%
        \hyxmp@extra@indent______<#1>%
      }%
%    \end{macrocode}
% \begin{macro}{\@elt@first}
% The first element of the list is output as is.
%    \begin{macrocode}
      \def\@elt@first##1{%
        \hyxmp@add@to@xml{##1}%
        \let\@elt=\@elt@rest
      }%
%    \end{macrocode}
% \begin{macro}{\@elt@rest}
% The remaining elements of the list are output with a preceding line
% separator (|\xmplinesep|).
%    \begin{macrocode}
      \def\@elt@rest##1{%
        \hyxmp@add@to@xml{\xmplinesep##1}%
      }%
%    \end{macrocode}
% \begin{macro}{\@elt}
% Re-encode the text from \term{Unicode} if necessary.  Then redefine
% |\@elt| to insert a line separator between terms.
%    \begin{macrocode}
      \let\@elt=\@elt@first
      \hyxmp@xmlify{#2}%
      \hyxmp@commas@to@list\hyxmp@list{\hyxmp@xmlified}%
      \hyxmp@list
      \hyxmp@add@to@xml{</#1>^^J}%
    \egroup
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@iptc@schema}
% Add properties defined by the \acro{IPTC} Photo Metadata
% schema~\cite{IPTC2010:photo-meta} to the |\hyxmp@xml| macro.  We
% currently support only the \xmpprop{Iptc4xmpCore:CreatorContactInfo}
% property, although this is a structure containing multiple fields.
% \changes{v2.2}{2012/12/07}{Added this macro}
% \changes{v2.9}{2016/04/23}{Use \textsf{Iptc4xmpCore} instead of
%   \textsf{Iptc4ContInfo} as the contact-information metadata prefix.
%   Leonid Sinev reports that Acrobat's \acro{PDF/A} validator seems to
%   prefer \textsf{Iptc4xmpCore}}
% \changes{v4.0}{2019/03/09}{Moved the definition of
%   \protect\cs{hyxmp@iptc@data} from here into
%   \protect\cs{hyxmp@check@iptc@data}}
% \changes{v4.0}{2019/03/16}{Renamed this macro to
%   \protect\cs{hyxmp@iptc@schema} from
%   \protect\cs{hyxmp@photometa@schema}}
% \changes{v4.0}{2019/03/16}{Rewrote this macro entirely to correct
%   the use of fields within a structure}
%    \begin{macrocode}
\gdef\hyxmp@iptc@schema{%
%    \end{macrocode}
% Because we currently support only
% \xmpprop{Iptc4xmpCore:CreatorContactInfo} it suffices to check if we
% have any relevant data.  If so, we instantiate a
% \xmpprop{Iptc4xmpCore:ContactInfo} structure with all available
% fields.
%    \begin{macrocode}
  \ifx\hyxmp@iptc@data\@empty
  \else
    \hyxmp@add@to@xml{%
______<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource">^^J%
    }%
%    \end{macrocode}
% We locally redefine |\hyxmp@extra@indent| to increase the indentation
% of the assignments to \xmpprop{Iptc4xmpCore:CreatorContactInfo}'s
% fields.
%    \begin{macrocode}
    \bgroup
      \edef\hyxmp@extra@indent{\hyxmp@extra@indent\space\space}%
      \hyxmp@list@to@lines{Iptc4xmpCore:CiAdrExtadr}{\@pdfcontactaddress}%
      \hyxmp@add@simple{Iptc4xmpCore:CiAdrCity}{\@pdfcontactcity}%
      \hyxmp@add@simple{Iptc4xmpCore:CiAdrRegion}{\@pdfcontactregion}%
      \hyxmp@add@simple{Iptc4xmpCore:CiAdrPcode}{\@pdfcontactpostcode}%
      \hyxmp@add@simple{Iptc4xmpCore:CiAdrCtry}{\@pdfcontactcountry}%
%    \end{macrocode}
% \begin{macro}{\xmplinesep}
% The \acro{IPTC} standard states that sets of telephone numbers, email
% addresses, and \acro{URL}s for the contact person or institution,
% ``[m]ay have to be separated by a comma in the user
% interface''~\cite{IPTC2010:photo-meta}.  This is rather ambiguous:
% Does the comma appear \emph{only} in the user interface or also in the
% generated \acro{XML}\@?  Here we assume the latter interpretation and
% temporarily redefine |\xmplinesep| as a comma and use
% |\hyxmp@list@to@lines| to insert the data.  Unlike
% |\hyxmp@add@simple|, this approach trims all spaces surrounding commas.
%    \begin{macrocode}
      \def\xmplinesep{,}%
      \hyxmp@list@to@lines{Iptc4xmpCore:CiTelWork}{\@pdfcontactphone}%
      \hyxmp@list@to@lines{Iptc4xmpCore:CiEmailWork}{\@pdfcontactemail}%
      \hyxmp@list@to@lines{Iptc4xmpCore:CiUrlWork}{\@pdfcontacturl}%
    \egroup
    \hyxmp@add@to@xml{%
______</Iptc4xmpCore:CreatorContactInfo>^^J%
    }%
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The PRISM Basic Metadata schema}
% \label{sec:prism-meta}
%
% \begin{schemadesc}[PRISM Basic Metadata]{\protect\acro{PRISM} Basic Metadata}
%
% \begin{macro}{\hyxmp@prism@schema}
% \changes{v4.0}{2019/03/10}{Added this macro}
% Add properties defined by the \acro{PRISM} Basic Metadata
% schema~\cite{PRISM2012:basic-meta}.
%    \begin{macrocode}
\newcommand*{\hyxmp@prism@schema}{%
  \ifx\hyxmp@prism@data\@empty
  \else
    \hyxmp@add@simple{prism:complianceProfile}{three}%
  \fi
  \hyxmp@add@simple@lang{prism:subtitle}{\@pdfsubtitle}%
  \hyxmp@add@simple@lang{prism:publicationName}{\@pdfpublication}%
  \hyxmp@add@simple{prism:aggregationType}{\@pdfpubtype}%
  \hyxmp@add@simple@lang{prism:bookEdition}{\@pdfbookedition}%
  \hyxmp@add@simple{prism:volume}{\@pdfvolumenum}%
  \hyxmp@add@simple{prism:number}{\@pdfissuenum}%
  \hyxmp@add@simple{prism:pageRange}{\@pdfpagerange}%
  \hyxmp@add@simple{prism:isbn}{\@pdfisbn}%
  \hyxmp@add@simple{prism:issn}{\@pdfissn}%
  \hyxmp@add@simple{prism:eIssn}{\@pdfeissn}%
  \hyxmp@add@simple{prism:doi}{\@pdfdoi}%
  \hyxmp@add@simple{prism:url}{\@pdfurl}%
  \hyxmp@add@simple{prism:byteCount}{\@pdfbytes}%
  \hyxmp@add@simple{prism:pageCount}{\@pdfnumpages}%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
%
% \subsubsection{The Journal Article Versions (JAV) schema}
% \label{sec:niso-jav-meta}
%
% \begin{schemadesc}{Journal Article Versions}
%
% \begin{macro}{\hyxmp@jav@schema}
% \changes{v5.5}{2020/07/23}{Added this macro}
% Add properties defined by the \acro{NISO}/\acro{ALPSP} Journal Article
% Versions schema~\cite{NISO2008:jav}.
%    \begin{macrocode}
\newcommand*{\hyxmp@jav@schema}{%
  \hyxmp@add@simple{jav:journal_article_version}{\@pdfpubstatus}%
}
%    \end{macrocode}
% \end{macro}
%
% \end{schemadesc}
%
% \subsubsection{The XMP Paged-Text schema}
% \label{sec:xmp-paged-text}
%
% \begin{schemadesc}[XMP Paged-Text]{\protect\acro{XMP} Paged-Text}
%
% \begin{macro}{\hyxmp@xmptpg@schema}
% The \acro{XMP} Paged-Text schema~\cite{Adobe2012:XMP} includes
% properties related to the construction of the \acro{PDF} file itself.
% We acquire most of this information through \LuaTeX\ mechanisms and
% therefore include much less information when run from other \TeX\ engines.
% \changes{v5.5}{2020/07/25}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@xmptpg@schema}{%
  \ifLuaTeX
    \luadirect{write_xmp_font_list(\the\hyxmp@cct)}%
  \fi
  \hyxmp@add@simple{xmpTPg:NPages}{\@pdfnumpages}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@cct}
% We store the current category-code table to ensure that
% |write_xmp_font_list|'s output uses our redefined category codes.
%    \begin{macrocode}
\ifLuaTeX
  \newcatcodetable\hyxmp@cct
  \savecatcodetable\hyxmp@cct
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@prot@us}
% Define an underscore character that's protected from being converted
% into a space when passed to \cs{hyxmp@add@to@xml}.  \cs{hyxmp@prot@us}
% is used within |write_xmp_font_list| (below) in particular to typeset
% filenames that may contain underscores.
%    \begin{macrocode}
\bgroup
  \catcode`\_=11
  \gdef\hyxmp@prot@us{_}%
\egroup
%    \end{macrocode}
% \end{macro}
%
% Here we define a Lua\index{Lua} function, |write_xmp_font_list|, that
% writes font information to the \acro{XMP} packet.
% \changes{v5.6}{2020/10/02}{Make \protect\texttt{write\_xmp\_font\_list}
%   robust to fonts loaded using
%   \protect\href{https://en.wikipedia.org/wiki/HarfBuzz}{HarfBuzz}.
%   Thanks to John Lienhard for the bug report}
% \changes{v5.6}{2020/10/02}{Don't inadvertently replace underscores in
%   filenames when writing font-related metadata}
%    \begin{macrocode}
\ifLuaTeX
  \begin{luacode*}
function write_xmp_font_list (cct)
    local function show_field(name, ...)
    for i = 1, select("#", ...) do
      local val = select(i, ...)
      if val then
        local xml = string.gsub(val, "&", "&amp;")
        xml = string.gsub(xml, "<", "&lt;")
        xml = string.gsub(xml, ">", "&gt;")
        xml = string.gsub(xml, "_", "\\hyxmp@prot@us ")
        tex.print(cct, "____________<stFnt:" .. name .. ">" ..
                  xml .. "</stFnt:" .. name .. ">^^J%")
        return
      end
    end
  end
  tex.print(cct, "\\hyxmp@add@to@xml{%")
  tex.print(cct, "______<xmpTPg:Fonts>^^J%")
  tex.print(cct, "________<rdf:Bag>^^J%")
  for i, f in font.each() do
    tex.print(cct, "__________<rdf:li rdf:parseType=\"Resource\">^^J%")
    if f.filename then
      local fname = string.gsub(f.filename, "^harfloaded:(.*)", "%1")
      local info = fontloader.info(fname)
      if info then
        show_field("fontFace", info.fullname)
        show_field("fontFamily", info.familyname)
        show_field("fontName", info.fontname)
        show_field("versionString", info.version)
      end
      local baseName = string.gsub(f.filename, ".*[/\\](.*)", "%1")
      show_field("fontFileName", baseName)
    else
      show_field("fontName", f.psname, f.fullname, f.name)
    end
    if f.format and f.format ~= "unknown" then
      show_field("fontType", f.format)
    end
    tex.print(cct, "__________</rdf:li>^^J%")
  end
  tex.print(cct, "________</rdf:Bag>^^J%")
  tex.print(cct, "______</xmpTPg:Fonts>^^J%")
  tex.print(cct, "}")
end
  \end{luacode*}
\fi
%    \end{macrocode}
%
% \end{schemadesc}
%
%
% \subsubsection{XMP extension schemata}
% \label{sec:extension-schemata}
%
% Not all of the schemata supported by \pkgname{hyperxmp} are predefined
% by \acro{XMP}.  \acro{PDF/A} conversion would normally fail for
% documents that employ ``custom'' schemata.  However, this problem can
% be circumvented by declaring non-standard schemata in the \acro{XMP}
% packet itself, following a technique described in a PDF Association
% technical note~\cite{PDFA2008:ext-schemas}.  In this section, we
% declare only those schemata we actually use.
%
% \begin{macro}{\hyxmp@check@iptc@data}
% \begin{macro}{\hyxmp@iptc@data}
% Define |\hyxmp@iptc@data| as the concatenation of all \acro{IPTC}
% photo metadata supplied by the document.
%    \begin{macrocode}
\newcommand*{\hyxmp@check@iptc@data}{%
  \edef\hyxmp@iptc@data{%
    \@pdfcontactaddress
    \@pdfcontactcity
    \@pdfcontactregion
    \@pdfcontactpostcode
    \@pdfcontactcountry
    \@pdfcontactphone
    \@pdfcontactemail
    \@pdfcontacturl
  }%
}%
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@check@prism@data}
% \begin{macro}{\hyxmp@prism@data}
% Define |\hyxmp@prism@data| as the concatenation of all \acro{PRISM}
% metadata supplied by the document.
%    \begin{macrocode}
\newcommand*{\hyxmp@check@prism@data}{%
  \edef\hyxmp@prism@data{%
    \@pdfbookedition
    \@pdfbytes
    \@pdfdoi
    \@pdfeissn
    \@pdfisbn
    \@pdfissn
    \@pdfissuenum
    \@pdfnumpages
    \@pdfpagerange
    \@pdfpublication
    \@pdfpubtype
    \@pdfsubtitle
    \@pdfurl
    \@pdfvolumenum
  }%
}%
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@check@jav@data}
% \begin{macro}{\hyxmp@jav@data}
% Define |\hyxmp@jav@data| as the concatenation of all \acro{JAV}
% metadata supplied by the document.
%    \begin{macrocode}
\newcommand*{\hyxmp@check@jav@data}{%
  \edef\hyxmp@jav@data{%
    \@pdfpubstatus
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\hyxmp@begin@extension@decls}
% Begin a block of \acro{XML} tags that indicates we're declaring one or
% more extension schemata.
%    \begin{macrocode}
\newcommand*{\hyxmp@begin@extension@decls}{%
  \hyxmp@add@to@xml{%
______<pdfaExtension:schemas>^^J%
________<rdf:Bag>^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@end@extension@decls}
% End the block of \acro{XML} tags begun by |\hyxmp@begin@extension@decls|.
%    \begin{macrocode}
\newcommand*{\hyxmp@end@extension@decls}{%
  \hyxmp@add@to@xml{%
________</rdf:Bag>^^J%
______</pdfaExtension:schemas>^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@begin@ext@decl}
% Begin the declaration of a single extension schema.
% |\hyxmp@begin@ext@decl| accepts the schema's name, prefix, and
% namespace URI.
% \changes{v4.0}{2019/03/15}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@begin@ext@decl}[3]{%
  \hyxmp@add@to@xml{%
__________<rdf:li rdf:parseType="Resource">^^J%
____________<pdfaSchema:schema>#1</pdfaSchema:schema>^^J%
____________<pdfaSchema:prefix>#2</pdfaSchema:prefix>^^J%
____________<pdfaSchema:namespaceURI>#3</pdfaSchema:namespaceURI>^^J%
____________<pdfaSchema:property>^^J%
______________<rdf:Seq>^^J%
  }%
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@end@ext@decl}
% End the declaration of a single extension schema.
% \changes{v4.0}{2019/03/15}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@end@ext@decl}{%
  \hyxmp@add@to@xml{%
______________</rdf:Seq>^^J%
____________</pdfaSchema:property>^^J%
__________</rdf:li>^^J%
  }%
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@declare@property}
% Declare a single extension-schema property.  |\hyxmp@declare@property|
% takes as input an optional type (defaults to \xmpterm{Text}) and a
% mandatory name, category, and description.
% \changes{v4.0}{2019/03/15}{Added this macro}
% \changes{v5.0}{2020/02/21}{Insert the property name (\string\texttt{\#2})
%   verbatim}
%    \begin{macrocode}
\newcommand{\hyxmp@declare@property}[4][Text]{%
  \hyxmp@add@to@xml{%
________________<rdf:li rdf:parseType="Resource">^^J%
__________________<pdfaProperty:name>}%
  \xdef\hyxmp@xml{\hyxmp@xml#2}%
  \hyxmp@add@to@xml{</pdfaProperty:name>^^J%
__________________<pdfaProperty:valueType>#1</pdfaProperty:valueType>^^J%
__________________<pdfaProperty:category>#3</pdfaProperty:category>^^J%
__________________<pdfaProperty:description>#4</pdfaProperty:description>^^J%
________________</rdf:li>^^J%
  }%
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@declare@field}
% Declare a single field in a custom datatype required by an extension
% schema.  |\hyxmp@declare@field| takes as input an optional type
% (defaults to \xmpterm{Text}) and a mandatory name and description.
% \changes{v4.0}{2019/03/16}{Replaced
%   \protect\cs{hyxmp@declare@resource} with this macro}
%    \begin{macrocode}
\newcommand{\hyxmp@declare@field}[3][Text]{%
  \hyxmp@add@to@xml{%
______________________<rdf:li rdf:parseType="Resource">^^J%
________________________<pdfaField:name>#2</pdfaField:name>^^J%
________________________<pdfaField:valueType>#1</pdfaField:valueType>^^J%
________________________<pdfaField:description>#3</pdfaField:description>^^J%
______________________</rdf:li>^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdf@extensions}
% Declare the Adobe \acro{PDF} schema.
% \changes{v5.0}{2020/02/27}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdf@extensions}{%
  \hyxmp@begin@ext@decl
      {Adobe PDF Schema}%
      {pdf}%
      {http://ns.adobe.com/pdf/1.3/}%
  \hyxmp@declare@property
      {Trapped}%
      {internal}%
      {Indication if the document has been modified to include trapping information}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@mm@extensions}
% Declare the \acro{XMP} Media Management schema.
% \changes{v4.0}{2019/03/15}{Added this macro}
% \changes{v5.5}{2020/07/23}{Corrected the type of
%   \protect\xmpprop{xmpMM:RenditionClass}.  Thanks to Thorsten Wi{\ss}mann
%   for the bug report and patch}
%    \begin{macrocode}
\newcommand*{\hyxmp@mm@extensions}{%
  \hyxmp@begin@ext@decl
      {XMP Media Management Schema}%
      {xmpMM}%
      {http://ns.adobe.com/xap/1.0/mm/}%
  \hyxmp@declare@property
      [URI]
      {DocumentID}%
      {internal}%
      {UUID based identifier for all versions and renditions of a document}%
  \hyxmp@declare@property
      [URI]
      {InstanceID}%
      {internal}%
      {UUID based identifier for specific incarnation of a document}%
  \hyxmp@declare@property
      {VersionID}%
      {internal}%
      {Document version identifier}%
  \hyxmp@declare@property
      [RenditionClass]%
      {RenditionClass}%
      {internal}%
      {The manner in which a document is rendered}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfa@id@extensions}
% Declare the \acro{PDF/A} Identification schema~\cite{PDFA2008:xmp-props}.
% \changes{v4.0}{2019/03/15}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfa@id@extensions}{%
  \hyxmp@begin@ext@decl
      {PDF/A Identification Schema}%
      {pdfaid}%
      {http://www.aiim.org/pdfa/ns/id/}%
  \hyxmp@declare@property
      [Integer]%
      {part}%
      {internal}%
      {Part of PDF/A standard}%
  \hyxmp@declare@property
      {conformance}%
      {internal}%
      {Conformance level of PDF/A standard}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfua@id@extensions}
% Declare the \acro{PDF/UA} Universal Accessibility schema.
% \changes{v5.0}{2020/02/15}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfua@id@extensions}{%
  \hyxmp@begin@ext@decl
      {PDF/UA Universal Accessibility Schema}%
      {pdfuaid}%
      {http://www.aiim.org/pdfua/ns/id/}%
  \hyxmp@declare@property
      [Integer]%
      {part}%
      {internal}%
      {Part of ISO 14289 standard}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@pdfx@id@extensions}
% Declare the schema used pre-\PDFstd{X}{4}{}{}.  Because Adobe Acrobat DC
% (at least) defines this even for \PDFstd{X}{4}{}{} and later, we follow
% suit.
% \changes{v5.0}{2020/02/26}{Added this macro}
%    \begin{macrocode}
\newcommand*{\hyxmp@pdfx@id@extensions}{%
  \ifx\hyxmp@pdfx@major\empty
  \else
    \hyxmp@begin@ext@decl
        {Adobe Document Info PDF/X eXtension Schema}%
        {pdfx}%
        {http://ns.adobe.com/pdfx/1.3/}%
    \hyxmp@declare@property
        {GTS_PDFXVersion}%
        {internal}%
        {ID of PDF/X standard}%
    \hyxmp@declare@property
        {GTS_PDFXConformance}%
        {internal}%
        {Conformance level of PDF/X standard}%
    \hyxmp@end@ext@decl
  \fi
%    \end{macrocode}
% Declare the schema used in \PDFstd{X}{4}{}{} and later versions.
%    \begin{macrocode}
  \@hyxmp@count=0\hyxmp@pdfx@major\relax
  \ifnum\@hyxmp@count>3
    \hyxmp@begin@ext@decl
        {PDF/X ID Schema}%
        {pdfxid}%
        {http://www.npes.org/pdfx/ns/id/}%
    \hyxmp@declare@property
        {GTS_PDFXVersion}%
        {internal}%
        {ID of PDF/X standard}%
    \hyxmp@end@ext@decl
  \fi
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@iptc@extensions}
% \changes{v2.2}{2012/12/13}{Added this macro to support
%   \acro{PDF/A} generation}
% \changes{v2.3}{2013/01/08}{Gave the
%   \xmpprop{Iptc4xmpCore:CreatorContactInfo} fields a unique
%   \xmpprop{pdfaType:prefix} to better support conversion of the
%   document to \acro{PDF/A}}
% \changes{v4.0}{2019/03/09}{Moved the header code from here into
%   \protect\cs{hyxmp@begin@extension@decls} and the trailer code
%   from here into \protect\cs{hyxmp@end@extension@decls}}
% \changes{v4.0}{2019/03/16}{Rewrote to more closely honor the
%   \acro{XMP} specification}
% Because \acro{IPTC} metadata are not recognized by the \acro{PDF/A}
% standard, \acro{PDF/A} conversion would normally fail for documents
% that utilize \acro{IPTC} metadata.  Declaring the \acro{IPTC}
% metadata we support enables the document to be converted to
% \acro{PDF/A} format.
%    \begin{macrocode}
\newcommand*{\hyxmp@iptc@extensions}{%
  \hyxmp@begin@ext@decl
      {IPTC Core Schema}%
      {Iptc4xmpCore}%
      {http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/}%
  \hyxmp@declare@property
      [ContactInfo]
      {CreatorContactInfo}
      {external}
      {Document creator's contact information}
%    \end{macrocode}
% We can't call |\hyxmp@end@ext@decl| because we need first need to
% define the \xmpprop{Iptc4xmpCore:ContactInfo} structure.
%    \begin{macrocode}
  \hyxmp@add@to@xml{%
______________</rdf:Seq>^^J%
____________</pdfaSchema:property>^^J%
____________<pdfaSchema:valueType>^^J%
______________<rdf:Seq>^^J%
________________<rdf:li rdf:parseType="Resource">^^J%
__________________<pdfaType:type>ContactInfo</pdfaType:type>^^J%
__________________<pdfaType:namespaceURI>http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/</pdfaType:namespaceURI>^^J%
__________________<pdfaType:prefix>Iptc4xmpCore</pdfaType:prefix>^^J%
__________________<pdfaType:description>%
                   Basic set of information to get in contact with a person%
                 </pdfaType:description>^^J%
__________________<pdfaType:field>^^J%
____________________<rdf:Seq>^^J%
  }%
  \hyxmp@declare@field
      {CiAdrCity}%
      {Contact information city}%
  \hyxmp@declare@field
      {CiAdrCtry}%
      {Contact information country}%
  \hyxmp@declare@field
      {CiAdrExtadr}%
      {Contact information address}%
  \hyxmp@declare@field
      {CiAdrPcode}%
      {Contact information local postal code}%
  \hyxmp@declare@field
      {CiAdrRegion}%
      {Contact information regional information such as state or province}%
  \hyxmp@declare@field
      {CiEmailWork}%
      {Contact information email address(es)}%
  \hyxmp@declare@field
      {CiTelWork}%
      {Contact information telephone number(s)}%
  \hyxmp@declare@field
      {CiUrlWork}%
      {Contact information Web URL(s)}%
  \hyxmp@add@to@xml{%
____________________</rdf:Seq>^^J%
__________________</pdfaType:field>^^J%
________________</rdf:li>^^J%
______________</rdf:Seq>^^J%
____________</pdfaSchema:valueType>^^J%
__________</rdf:li>^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@prism@extensions}
% \changes{v4.0}{2019/03/15}{Added this macro}
% Because \acro{PRISM} metadata are not recognized by the \acro{PDF/A}
% standard, \acro{PDF/A} conversion would normally fail for documents
% that utilize \acro{PRISM} metadata.  Declaring the \acro{PRISM}
% metadata we support enables the document to be converted to
% \acro{PDF/A} format.
%    \begin{macrocode}
\newcommand*{\hyxmp@prism@extensions}{%
  \hyxmp@begin@ext@decl
      {PRISM Basic Metadata}%
      {prism}%
      {http://prismstandard.org/namespaces/basic/3.0/}%
  \hyxmp@declare@property
      {complianceProfile}%
      {internal}%
      {PRISM specification compliance profile to which this document adheres}%
  \hyxmp@declare@property
      {publicationName}%
      {external}%
      {Publication name}%
  \hyxmp@declare@property
      {aggregationType}%
      {external}%
      {Publication type}%
  \hyxmp@declare@property
      {bookEdition}%
      {external}%
      {Edition of the book in which the document was published}%
  \hyxmp@declare@property
      {volume}%
      {external}%
      {Publication volume number}%
  \hyxmp@declare@property
      {number}%
      {external}%
      {Publication issue number within a volume}%
  \hyxmp@declare@property
      {pageRange}%
      {external}%
      {Page range for the document within the print version of its publication}%
  \hyxmp@declare@property
      {issn}%
      {external}%
      {ISSN for the printed publication in which the document was published}%
  \hyxmp@declare@property
      {eIssn}%
      {external}%
      {ISSN for the electronic publication in which the document was published}%
  \hyxmp@declare@property
      {isbn}%
      {external}%
      {ISBN for the publication in which the document was published}%
  \hyxmp@declare@property
      {doi}%
      {external}%
      {Digital Object Identifier for the document}%
  \hyxmp@declare@property
      [URL]
      {url}%
      {external}%
      {URL at which the document can be found}%
  \hyxmp@declare@property
      [Integer]
      {byteCount}%
      {internal}%
      {Approximate file size in octets}%
  \hyxmp@declare@property
      [Integer]
      {pageCount}%
      {internal}%
      {Number of pages in the print version of the document}%
  \hyxmp@declare@property
      {subtitle}%
      {external}%
      {Document's subtitle}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@jav@extensions}
% \changes{v5.5}{2020/07/23}{Added this macro}
% Because \acro{JAV} metadata are not recognized by the \acro{PDF/A}
% standard, \acro{PDF/A} conversion would normally fail for documents
% that utilize \acro{JAV} metadata.  Declaring the \acro{JAV} metadata
% we support enables the document to be converted to \acro{PDF/A}
% format.
%    \begin{macrocode}
\newcommand*{\hyxmp@jav@extensions}{%
  \hyxmp@begin@ext@decl
      {NISO/ALPSP Journal Article Versions}%
      {jav}%
      {http://www.niso.org/schemas/jav/1.0/}%
  \hyxmp@declare@property
      [Closed Choice of Text]%
      {journal_article_version}%
      {external}%
      {Article status, one of "AO", "SMUR", "AM", "P", "VoR", "CVoR", or "EVoR"}%
  \hyxmp@end@ext@decl
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@declare@extensions}
% Declare all \acro{XMP} extension schemata.  We'll always have at least
% one, the \acro{XMP} Media Management extensions, because we
% automatically generate \xmpprop{xmpMM:DocumentID} and
% \xmpprop{xmpMM:InstanceID}
% values.
%    \begin{macrocode}
\newcommand*{\hyxmp@declare@extensions}{%
  \hyxmp@begin@extension@decls
%    \end{macrocode}
% Declare the Adobe \acro{PDF} schema (always present).
%    \begin{macrocode}
  \hyxmp@pdf@extensions
%    \end{macrocode}
% Declare the \acro{XMP} Media Management extensions (always present).
%    \begin{macrocode}
  \hyxmp@mm@extensions
%    \end{macrocode}
% Declare the \acro{PDF/A} Identification extensions, but only when
% generating a \acro{PDF/A} document.
%    \begin{macrocode}
  \ifHy@pdfa
    \hyxmp@pdfa@id@extensions
  \fi
%    \end{macrocode}
% Conditionally declare the \acro{PDF/UA} Universal Accessibility
% extensions.
%    \begin{macrocode}
  \ifx\@pdfuapart\@empty
  \else
    \hyxmp@pdfua@id@extensions
  \fi
%    \end{macrocode}
% \begin{macro}{\next}
% Conditionally declare the \acro{PDF/X} extensions.
%    \begin{macrocode}
  \ifx\@pdfxversion\@empty
  \else
    \hyxmp@pdfx@id@extensions
  \fi
%    \end{macrocode}
% \end{macro}
% Conditionally declare \acro{IPTC} photo metadata extensions.
%    \begin{macrocode}
  \ifx\hyxmp@iptc@data\@empty
  \else
    \hyxmp@iptc@extensions
  \fi
%    \end{macrocode}
% Conditionally declare \acro{PRISM} basic metadata extensions.
%    \begin{macrocode}
  \ifx\hyxmp@prism@data\@empty
  \else
    \hyxmp@prism@extensions
  \fi
%    \end{macrocode}
% Conditionally declare \acro{JAV} metadata.
%    \begin{macrocode}
  \ifx\hyxmp@jav@data\@empty
  \else
    \hyxmp@jav@extensions
  \fi
%    \end{macrocode}
%    \begin{macrocode}
  \hyxmp@end@extension@decls
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Combining schemata into an XMP packet}
% \label{sec:combining-schemata}
%
% \begin{macro}{\hyxmp@bom}
% Define a macro for the \term{Unicode} byte-order marker (\acro{BOM}).
% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
%    \begin{macrocode}
\begingroup
  \ifhyxmp@unicodetex
    \lccode`\!="FEFF %
    \lowercase{%
      \gdef\hyxmp@bom{!}
    }%
  \else
    \catcode`\^^ef=12
    \catcode`\^^bb=12
    \catcode`\^^bf=12
    \gdef\hyxmp@bom{^^ef^^bb^^bf}%
  \fi
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@construct@packet}
% \changes{v1.1}{2006/05/21}{Explicitly set the category codes of
%   characters \string\meta{EF}, \string\meta{BB}, and
%   \string\meta{BF} to ``letter''.  Thanks to Daniel Sch\"omer for
%   the bug report}
% \changes{v2.0}{2012/08/02}{Modified by Heiko Oberdiek to use an
%   appropriate \acro{BOM} representation via
%   \texttt{\string\string\string\hyxmp@bom}}
% \begin{macro}{\hyxmp@xml}
% Successively add \acro{XML} data to |\hyxmp@xml| until we have
% something we can insert into the document's \acro{PDF} catalog.
%    \begin{macrocode}
\def\hyxmp@construct@packet{%
  \gdef\hyxmp@xml{}%
  \hyxmp@add@to@xml{<?xpacket begin="\hyxmp@bom" %
id="W5M0MpCehiHzreSzNTczkc9d"?>^^J%
<x:xmpmeta xmlns:x="adobe:ns:meta/">^^J%
__<rdf:RDF %
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns\hyxmp@hash">^^J%
____<rdf:Description rdf:about=""^^J%
%    \end{macrocode}
% Specify every namespace we can potentially use, even the ones we end
% up not actually using.
%    \begin{macrocode}
_____________________xmlns:pdf="http://ns.adobe.com/pdf/1.3/"^^J%
_____________________xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"^^J%
_____________________xmlns:dc="http://purl.org/dc/elements/1.1/"^^J%
_____________________xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"^^J%
_____________________xmlns:xmp="http://ns.adobe.com/xap/1.0/"^^J%
_____________________xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"^^J%
_____________________xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent\hyxmp@hash"^^J%
_____________________xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"^^J%
_____________________xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"^^J%
_____________________xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"^^J%
  }%
%    \end{macrocode}
% We make one exception to the rule of including every namespace we can
% potentially use: We don't define the \texttt{pdfxid} namespace unless
% the \acro{PDF/X} version (specified by the \optname{pdfxstandard})
% option is~4 or greater.  Otherwise, Adobe Acrobat---at least Adobe
% Acrobat DC 2020---alters the way it displays color.  (I believe it
% renders color in a printer gamut instead of a screen gamut.)
% \changes{v5.10}{2020/01/05}{Include the \string\texttt{pdfxid} namespace
%   only if the \protect\acro{PDF/X} version is~4 or greater.  Thanks to
%   John Lienhard for the bug report}
%    \begin{macrocode}
  \ifnum0\hyxmp@pdfx@major>3
    \hyxmp@add@to@xml{%
_____________________xmlns:pdfxid="http://www.npes.org/pdfx/ns/id/"^^J%
    }%
  \fi
%    \end{macrocode}
% Revert to ``include every namespace'' mode.
%    \begin{macrocode}
  \hyxmp@add@to@xml{%
_____________________xmlns:prism="http://prismstandard.org/namespaces/basic/3.0/"^^J%
_____________________xmlns:jav="http://www.niso.org/schemas/jav/1.0/"^^J%
_____________________xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"^^J%
_____________________xmlns:stFnt="http://ns.adobe.com/xap/1.0/sType/Font\hyxmp@hash"^^J%
_____________________xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"^^J%
_____________________xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"^^J%
_____________________xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema\hyxmp@hash"^^J%
_____________________xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property\hyxmp@hash"^^J%
_____________________xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type\hyxmp@hash"^^J%
_____________________xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field\hyxmp@hash">^^J%
  }%
%    \end{macrocode}
% Declare non-standard schemata.
%    \begin{macrocode}
  \hyxmp@check@iptc@data
  \hyxmp@check@prism@data
  \hyxmp@check@jav@data
  \hyxmp@declare@extensions
%    \end{macrocode}
% Insert all the metadata we know how to insert.
%    \begin{macrocode}
  \hyxmp@pdf@schema
  \hyxmp@xmpRights@schema
  \hyxmp@dc@schema
  \hyxmp@photoshop@schema
  \hyxmp@xmp@basic@schema
  \hyxmp@pdfa@id@schema
  \hyxmp@pdfua@id@schema
  \hyxmp@pdfx@id@schema
  \hyxmp@mm@schema
  \hyxmp@iptc@schema
  \hyxmp@prism@schema
  \hyxmp@jav@schema
  \hyxmp@xmptpg@schema
  \hyxmp@add@to@xml{%
____</rdf:Description>^^J%
__</rdf:RDF>^^J%
</x:xmpmeta>^^J%
\hyxmp@padding
<?xpacket end="w"?>^^J%
  }%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \subsection{Embedding the XMP packet}
%
% The \acro{PDF} specification says that ``a metadata stream may be
% attached to a document through the \pdfterm{Metadata} entry in the
% document catalogue''~\cite{Adobe2008:PDF} so that's what we do here.
%
% \begin{macro}{\hyxmp@embed@packet}
% \begin{macro}{\hyxmp@driver}
% Determine which \pkgname{hyperref} driver is in use and invoke the
% appropriate embedding function.
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet}{%
  \hyxmp@construct@packet
  \def\hyxmp@driver{hpdftex}%
  \ifx\hyxmp@driver\Hy@driver
    \hyxmp@embed@packet@pdftex
  \else
    \def\hyxmp@driver{hluatex}%
    \ifx\hyxmp@driver\Hy@driver
      \hyxmp@embed@packet@luatex
    \else
      \def\hyxmp@driver{hdvipdfm}%
      \ifx\hyxmp@driver\Hy@driver
        \hyxmp@embed@packet@dvipdfm
      \else
        \def\hyxmp@driver{hxetex}%
        \ifx\hyxmp@driver\Hy@driver
          \hyxmp@embed@packet@xetex
        \else
          \@ifundefined{pdfmark}{%
            \PackageWarningNoLine{hyperxmp}{%
              Unrecognized hyperref driver `\Hy@driver'.\MessageBreak
              \hyxmp@jobname.tex's XMP metadata will *not* be\MessageBreak
              embedded in the resulting file}%
          }{%
            \hyxmp@embed@packet@pdfmark
          }%
        \fi
      \fi
    \fi
  \fi
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsubsection{Embedding using \pdfTeX}
%
% Up to version~0.85, \LuaTeX\ supported the \pdfTeX\ primitives, and
% \pkgname{hyperref} didn't distinguish the two backends.  However, from
% \pkgname{hyperxmp}'s perspective there is one key difference: the
% effect of |\pdfcompresslevel| is local to a group in \pdfTeX\ but is
% global in \LuaTeX\@.
%
% The \acro{PDF} object representing the \acro{XMP} packet is supposed
% to include an uncompressed stream so it can be read by
% non-\acro{PDF}-aware tools.  However, we don't want to unnecessarily
% uncompress \emph{every} \acro{PDF} stream.  The solution, provided by
% Hans Hagen on the |luatex| mailing list (thread:
% \href{http://tug.org/pipermail/luatex/2016-July/006077.html}{``Leaving
%   a single \acro{PDF} object uncompressed''}, 6\,\textsc{Jul}\,2016),
% is to provide the |uncompressed| flag to |\pdfobj|.  Our definition of
% |\hyxmp@embed@packet@pdftex| uses the \pkgname{ifluatex} package to
% distinguish the \pdfTeX\ case from the pre-0.85 \LuaTeX\ case.
%
%    \begin{macrocode}
\RequirePackage{ifluatex}
%    \end{macrocode}
%
% \begin{macro}{\hyxmp@embed@packet@pdftex}
% Embed the \acro{XMP} packet using \pdfTeX\ primitives, which are
% supported by both \pdfTeX\ and pre-0.85 \LuaTeX.  The only difference
% is that in the former case we locally specify |\pdfcompresslevel=0| to
% leave the \acro{PDF} object uncompressed while in the latter case we
% pass the |uncompressed| flag to |\pdfobj| to achieve the same effect.
% \changes{v3.1}{2016/07/06}{Leave the \protect\acro{XMP} packet---and
%   only the \protect\acro{XMP} packet---uncompressed in both
%   \protect\pdfTeX\ and pre-0.85 \protect\LuaTeX}
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet@pdftex}{%
  \bgroup
    \ifluatex
    \else
      \pdfcompresslevel=0
    \fi
    \immediate\pdfobj \ifluatex uncompressed\fi stream attr {%
      /Type /Metadata
      /Subtype /XML
    }{\hyxmp@xml}%
    \pdfcatalog {/Metadata \the\pdflastobj\space 0 R}%
  \egroup
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Embedding using \LuaTeX~0.85+}
%
% \begin{macro}{\hyxmp@embed@packet@luatex}
% Embed the \acro{XMP} packet using \LuaTeX~0.85+ primitives.
% \changes{v3.0}{2016/07/02}{Added this macro}
% \changes{v3.1}{2016/07/06}{Updated to use
%   \protect\texttt{\string\string\string\pdfextension\ obj uncompressed}
%   as suggested by Hans Hagen}
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet@luatex}{%
  \immediate\pdfextension obj uncompressed stream attr {%
    /Type /Metadata
    /Subtype /XML
  }{\hyxmp@xml}%
  \pdfextension catalog {/Metadata \the\numexpr\pdffeedback lastobj\relax\space 0 R}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Embedding using any \texttt{pdfmark}-based backend}
%
% \begin{macro}{\hyxmp@embed@packet@pdfmark}
% Embed the \acro{XMP} packet using \pkgname{hyperref}'s |\pdfmark|
% command.  I believe |\pdfmark| is used by the \optname{dvipdf},
% \optname{dvipsone}, \optname{dvips}, \optname{dviwindo},
% \optname{nativepdf}, \optname{pdfmark}, \optname{ps2pdf},
% \optname{textures}, and \optname{vtexpdfmark} options to
% \pkgname{hyperref}, but I've tested only a few of those.
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet@pdfmark}{%
  \pdfmark{%
    pdfmark=/NamespacePush
  }%
  \pdfmark{%
    pdfmark=/OBJ,
    Raw={/_objdef \string{hyxmp@Metadata\string} /type /stream}%
  }%
  \pdfmark{%
    pdfmark=/PUT,
    Raw={\string{hyxmp@Metadata\string}
      2 dict begin
        /Type /Metadata def
        /Subtype /XML def
        currentdict
      end
    }%
  }%
  \pdfmark{%
    pdfmark=/PUT,
    Raw={\string{hyxmp@Metadata\string} (\hyxmp@xml)}%
  }%
  \pdfmark{%
    pdfmark=/Metadata,
    Raw={\string{Catalog\string} \string{hyxmp@Metadata\string}}%
  }%
  \pdfmark{%
    pdfmark=/NamespacePop
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Embedding using \texttt{dvipdfm}}
%
% \begin{macro}{\hyxmp@embed@packet@dvipdfm}
% Embed the \acro{XMP} packet using \cmdname{dvipdfm}-specific
% |\special| commands.  Note that \cmdname{dvipdfm} rather irritatingly
% requires us to count the number of characters in the |\hyxmp@xml|
% stream ourselves.
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet@dvipdfm}{%
  \hyxmp@string@len{\hyxmp@xml}%
  \special{pdf: object @hyxmp@Metadata
    <<
      /Type /Metadata
      /Subtype /XML
      /Length \the\@hyxmp@count
    >>
    stream^^J\hyxmp@xml endstream%
  }%
  \special{pdf: docview
    <<
      /Metadata @hyxmp@Metadata
    >>
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@string@len}
% Set |\@hyxmp@count| to the number of characters in a given string~(|#1|).
% The approach is first to tally the number of space characters then to
% tally the number of non-space characters.  While this is rather
% sloppy I haven't found a better way to achieve the same effect,
% especially given that all of the characters in |#1| have already been
% assigned their category codes.
%    \begin{macrocode}
\newcommand*{\hyxmp@string@len}[1]{%
  \@hyxmp@count=0
  \expandafter\hyxmp@count@spaces#1 {} %
  \expandafter\hyxmp@count@non@spaces#1{}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@count@spaces}
% Count the number of spaces in a given string.  We rely on the built-in
% pattern matching of \tex's |\def| primitive to pry one word at a time
% off the head of the input string.
%    \begin{macrocode}
\def\hyxmp@count@spaces#1 {%
  \def\hyxmp@one@token{#1}%
  \ifx\hyxmp@one@token\@empty
    \advance\@hyxmp@count by -1
  \else
    \advance\@hyxmp@count by 1
    \expandafter\hyxmp@count@spaces
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\hyxmp@count@non@spaces}
% Count the number of non-spaces in a given string.  Ideally, we'd count
% both spaces and non-spaces but \tex\ won't bind |#1| to a space
% character (category code~10).  Hence, in each iteration, |#1| is bound
% to the next non-space character only.
%    \begin{macrocode}
\newcommand*{\hyxmp@count@non@spaces}[1]{%
  \def\hyxmp@one@token{#1}%
  \ifx\hyxmp@one@token\@empty
  \else
    \advance\@hyxmp@count by 1
    \expandafter\hyxmp@count@non@spaces
  \fi
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Embedding using \XeTeX}
%
% \begin{macro}{\hyxmp@embed@packet@xetex}
% Embed the \acro{XMP} packet using \cmdname{xdvipdfmx}-specific
% |\special| commands.  I don't know how to tell \cmdname{xdvipdfmx}
% always to leave the \pdfterm{Metadata} stream uncompressed, so the
% \acro{XMP} metadata is likely to be missed by non-\acro{PDF}-aware
% \acro{XMP} viewers.
%    \begin{macrocode}
\newcommand*{\hyxmp@embed@packet@xetex}{%
  \special{pdf:stream @hyxmp@Metadata (\hyxmp@xml)
    <<
      /Type /Metadata
      /Subtype /XML
    >>
  }%
  \special{pdf:put @catalog
    <<
      /Metadata @hyxmp@Metadata
    >>
  }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Final clean-up}
% \label{sec:clean-up}
%
% As explained in Section~\ref{sec:initial-prep}, all invocations of
% \cs{AtEndPreamble} have been stored in \cs{hyxmp@aep@toks} rather than
% executed.  Now that \pkgname{hyperxmp} has been initialized
% completely, it is finally safe to execute the accumulated
% \cs{AtEndPreamble} stanzas.
%    \begin{macrocode}
\the\hyxmp@aep@toks
%    \end{macrocode}
%
% Having saved the category code of
% ``\,{\fontencoding{T1}\selectfont\textquotedbl}\,'' at the start of
% the package code (Section~\ref{sec:initial-prep}), we now restore that
% character's original category code.
%
%    \begin{macrocode}
\catcode`\"=\hyxmp@dq@code
%    \end{macrocode}
%
% \iffalse
%</package>
% \fi
%
% \iffalse
%<*doc-helper>
% \fi
%
% ^^A  There's not much point including the documentation helper code
% ^^A  in the documentation itself, but feel free to remove the
% ^^A  following |\iffalse| and matching |\fi| if you'd like to include
% ^^A  it.
% \iffalse
%
% \section{Documentation helper code}
%
% The following code is used to make |hyperxmp.pdf| compliant with the
% \PDFstd{A}{1}{b}{} standard, at least when built from \pdfLaTeX\ or
% \LuaLaTeX, but not currently \XeLaTeX\@.  We include this code in a
% separate file because (a)~it is less distracting squirreled away here
% than placed at the top of the |.dtx| file, and (b)~putting it in a
% separate file makes it easy to disable.  One simply needs to comment
% out the |\input{hyperxmp-stds}| line to produce an ordinary \acro{PDF}
% file, which offers the benefit of live hyperlinks in almost all
% \acro{PDF} readers.
%
%
% \subsection{Ensuring proper support}
%
% \begin{macro}{\next}
% We can't proceed without a color profile.  For this document we use a
% \acro{CMYK} profile, specifically uncoated FOGRA29L, as a small and
% thus safe color space.  As long as |FOGRA29L_uncoated.icc| lies in the
% \tex\ search path (which normally includes the current directory),
% we'll be able to find it.
%    \begin{macrocode}
\let\next=\endinput
\IfFileExists{FOGRA29L_uncoated.icc}
             {\let\next=\relax}
             {}
\next
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\next}
% We can't proceed unless we're running either \pdfLaTeX\ or
% \LuaLaTeX\@.  \XeLaTeX\ doesn't appear to support all of the
% mechanisms required below to support \PDFstd{A}{1}{b}{} compliance.
% If you know how to adapt the following code to \XeLaTeX, please
% contact the \pkgname{hyperxmp} maintainer.
%    \begin{macrocode}
\let\next=\endinput
\ifPDFTeX
  \let\next=\relax
\else
  \ifLuaTeX
    \usepackage{luatex85}
    \let\next=\relax
  \fi
\fi
\next
%    \end{macrocode}
% \end{macro}
%
% If we're here, we should be able to make |hyperxmp.pdf|
% \PDFstd{A}{1}{b}{}-compliant.
%    \begin{macrocode}
\def\wantpdfstandards{}
\typeout{Generating PDF/A-1b compliant hyperxmp documentation.}
%    \end{macrocode}
%
%
% \subsection{Complying with the PDF/A-1b standard}
%
% We can't specify \PDFstd{A}{1}{b}{} compliance until after both
% \pkgname{hyperref} and \pkgname{hyperxmp} are loaded so we do so at
% the beginning of the document.
%    \begin{macrocode}
\AtBeginDocument{%
  \hypersetup{%
    pdfapart=1,
    pdfaconformance=b
  }%
}
%    \end{macrocode}
%
% \PDFstd{A}{1}{b}{} forbids object compression.  This is normally the
% default for \pdfLaTeX, but the \TeX\ Live distribution changes the
% default to compression level~2.  Here we explicitly change it back
% to~0.
%    \begin{macrocode}
\pdfobjcompresslevel=0
%    \end{macrocode}
%
% We specify an uncoated FOGRA29 output intent for both
% \PDFstd{A}{1}{b}{} and \acro{PDF/X} (all versions).
%    \begin{macrocode}
\immediate\pdfobj stream attr {/N 4} file {FOGRA29L_uncoated.icc}
\edef\iccobj{\the\pdflastobj}
\pdfcatalog{%
  /OutputIntents [
    <<
      /Type /OutputIntent
      /S /GTS_PDFA1
      /DestOutputProfile \iccobj\space 0 R
      /OutputConditionIdentifier (Uncoated FOGRA29)
      /Info (FOGRA29L)
    >>
    <<
      /Type /OutputIntent
      /S /GTS_PDFX
      /DestOutputProfile \iccobj\space 0 R
      /OutputConditionIdentifier (Uncoated FOGRA29)
      /Info (FOGRA29L)
    >>
  ]
}
%    \end{macrocode}
%
% \begin{macro}{\HyColor@HyperrefBorderColor}
% We just specified a \acro{CMYK} color profile, but \pkgname{hyperref}
% normally produces \acro{RGB} link borders.  The following code
% instructs \pkgname{hyperref} to accept \acro{CMYK} colors.
%    \begin{macrocode}
\makeatletter
\AtBeginDocument{%
  \let\HyColor@HyperrefBorderColor\HyColor@XZeroOneThreeFour
}
\makeatother
%    \end{macrocode}
% \end{macro}
%
% \pkgname{hyperref}'s default colors are specified as \acro{RGB}\@.  We
% need to reassign them so they take on \acro{CMYK} values.  (Note that
% the main document already loaded the \pkgname{xcolor} package with the
% \optname{cmyk} option.)  Annoyingly, very few \acro{PDF} readers
% correctly color hyperlinks defined with \acro{CMYK} link borders.  At
% the time of this writing (March 2020), Adobe Acrobat DC displays the
% \emph{reverse} of the specified color, presumably because it always
% interprets the first three color channels as red, green, and blue.
% Other browsers display no border or a black border.  This is not a
% huge problem in practice because (a)~it's more important to be able to
% distinguish hyperlinks from regular text than to render with correct
% border colors and (b)~\acro{PDF} readers may suppress hyperlink
% borders anyway for \PDFstd{A}{1}{b}{} documents.
%    \begin{macrocode}
\AtBeginDocument{%
  \hypersetup{%
    citebordercolor=green,
    linkbordercolor=red,
    urlbordercolor=cyan
  }%
}
%    \end{macrocode}
%
% \begin{macro}{\@tempdima}
% \begin{macro}{\boxwd}
% \begin{macro}{\boxht}
% \begin{macro}{\next}
% Explicitly specify the \pdfterm{BleedBox} and \pdfterm{TrimBox} to use
% for every page of the documentation.
%    \begin{macrocode}
\makeatletter
\@tempdima=0.996264\paperwidth
\edef\boxwd{\strip@pt\@tempdima}
\@tempdima=0.996264\paperheight
\edef\boxht{\strip@pt\@tempdima}
\makeatother
\edef\next{%
  \protect\pdfpageattr{
    /BleedBox [0.0 0.0 \boxwd\space \boxht]
    /TrimBox [0.0 0.0 \boxwd\space \boxht]
    /StructParents 0
    /Tabs /S
  }%
}
\next
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \fi
%
% \iffalse
%</doc-helper>
% \fi
%
% \Finale
\endinput
