summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/hyperxmp/hyperxmp.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/hyperxmp/hyperxmp.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/hyperxmp/hyperxmp.dtx')
-rw-r--r--macros/latex/contrib/hyperxmp/hyperxmp.dtx5055
1 files changed, 5055 insertions, 0 deletions
diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.dtx b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
new file mode 100644
index 0000000000..a5aa24a146
--- /dev/null
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
@@ -0,0 +1,5055 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2019 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>
+ [2019/04/05 v4.1 Store hyperref metadata in XMP format]
+%</package>
+%
+%<*driver>
+\bgroup
+ \catcode`\&=11
+ \gdef\levelchar{&}
+\egroup
+\documentclass{ltxdoc}
+\usepackage{graphicx}
+\usepackage{color}
+\usepackage{tocbibind}
+\usepackage{microtype}
+\usepackage{needspace}
+\usepackage{varioref}
+\usepackage{alltt}
+\usepackage{multicol}
+\usepackage{makeidx}
+\usepackage[utf8]{inputenc}
+\usepackage{hyperxmp}
+\usepackage[unicode,bookmarksopen,bookmarksopenlevel=2,bookmarksnumbered]{hyperref}
+\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) 2019, 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},
+ pdfurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/hyperxmp.pdf},
+ baseurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/}
+}
+
+\begin{document}
+ \DocInput{hyperxmp.dtx}
+ \Needspace{10\baselineskip}
+ \phantomsection\addcontentsline{toc}{section}{Change History}
+ \PrintChanges
+ \makeatletter
+ \let\orig@index@prologue=\index@prologue
+ \def\index@prologue{%
+ \phantomsection\addcontentsline{toc}{section}{Index}
+ \orig@index@prologue
+ }%
+ \makeatother
+ \Needspace{12\baselineskip}
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{2095}
+%
+% \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}
+%
+% ^^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,\edef,\egroup,\else,\end,\endcsname,\endgroup}
+% \DoNotIndex{\expandafter,\fi,\futurelet,\g@addto@macro,\gdef,\global,\if}
+% \DoNotIndex{\ifcase,\ifnum,\ifx,\immediate,\lccode,\let,\loop,\lowercase}
+% \DoNotIndex{\multiply,\newcommand,\noexpand,\or,\relax,\repeat,\space}
+% \DoNotIndex{\string,\the,\toks,\uccode,\uppercase,\usepackage,\xdef}
+%
+% ^^A Define a few logical styles.
+% \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}}
+% \DeclareRobustCommand{\pkgname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \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]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \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
+% \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{\Lua}{^^A
+% Lua\index{Lua}^^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 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. 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/}{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 applications to identify and
+% categorize the document.
+%
+% \paragraph{What metadata does \textsf{hyperxmp} process?}
+% \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 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} compliance level and version (\xmpprop{pdfaid:part} and \xmpprop{pdfaid:conformance})
+% \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 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 type of document (\xmpprop{dc:type})
+% \item type of parent publication (\xmpprop{prism:aggregationType})
+% \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.
+%
+% \paragraph{How does \textsf{hyperxmp} compare to the \textsf{xmpincl}
+% package?}
+% The short answer is that \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.
+%
+% \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}
+% \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{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{pdfpubtype}
+% \item \optname{pdfsource}
+% \item \optname{pdfsubtitle}
+% \item \optname{pdftype}
+% \item \optname{pdfurl}
+% \item \optname{pdfversionid}
+% \item \optname{pdfvolumenum}
+% \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. \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}.
+%
+% \Needspace{6\baselineskip}
+% \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
+% ``|x-default|'' as the metadata language. Note that ``|x-default|''
+% metadata are always included in addition to the specified metadata
+% language, as the user reading the document may not have specified a
+% language preference.
+%
+% \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}.
+%
+% 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.
+%
+% 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. 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}|.
+%
+% The number of pages in the published, print version of the document
+% can be expressed with \moptname{pdfnumpages}.
+% Note~\ref{note:page-counting} on page~\pageref{note:page-counting}
+% explains how to automatically assign a value to \optname{pdfnumpages}.
+%
+% \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.
+%
+% 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. This feature is easiest to
+% use in conjunction with \pdfTeX's |\pdffilesize| primitive:
+% ``|pdfbytes={\pdffilesize{\jobname.pdf}}|''. Note that this requires
+% a second run of |pdftex| because it queries the size of the \acro{PDF}
+% file from the \emph{previous} run.
+%
+% A rarely needed option, \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.
+%
+% Two other rarely needed options, \moptname{pdfaconformance} and
+% \moptname{pdfapart}, 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 \acro{PDF/A}-\textsc{1b}
+% standard. These can be changed (with caution) to assert that the
+% document abides by a different standard
+% (e.g.,~\acro{PDF/A}-\textsc{2u}).
+%
+% \bigskip
+%
+% It is usually more convenient to provide values for those options 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},
+% pdfnumpages={17},
+% pdfissn={0003-3804},
+% pdfeissn={1521-3889},
+% 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},
+% pdfbytes={\pdffilesize{\jobname.pdf}} % Requires pdflatex
+% }
+% \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 \LaTeX~$+$ Dvipdfm
+% \item \LaTeX~$+$ \Dvips~$+$ Adobe Acrobat Distiller
+% \item \XeLaTeX
+% \end{itemize}
+%
+% \noindent
+% Unfortunately, the \LaTeX~$+$ \Dvips~$+$ \term{Ghostscript} path
+% doesn't work.
+% \href{http://bugs.ghostscript.com/show_bug.cgi?id=690066}{Ghostscript
+% bug report~\#690066}, closed with ``\textsc{wontfix}'' status on
+% 2012-05-28, explains that \term{Ghostscript} doesn't honor the
+% \pdfterm{Metadata} tag needed to inject a custom \acro{XMP} packet.
+% Instead, \term{Ghostscript} fabricates an \acro{XMP} packet of its own
+% based on the metadata it finds in the \acro{PDF} file's \pdfterm{Info}
+% dictionary (\pdfterm{Author}, \pdfterm{Title}, \pdfterm{Subject}, and
+% \pdfterm{Keywords}).
+%
+% \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}
+% 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. 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 \optname{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}
+% \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}
+% \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,
+% ``|x-default|'' otherwise. An implication of automatic
+% metadata specification is that 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.
+%
+% \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{Automatic page counting}
+% \label{note:page-counting}
+% Although \optname{pdfnumpages} and \optname{pdfpagerange} are 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 to keep track of the
+% number of pages.
+%
+% \begin{verbatim}
+% \hypersetup{%
+% pdfnumpages={\ref*{TotPages}}
+% }
+% \end{verbatim}
+%
+% \pkgname{totpages} can likewise help generate \optname{pdfpagerange}.
+% For documents numbered from~1 to~$n$, a simple
+%
+% \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 title page can be either
+% omitted or listed as |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{pdfnumpages} and \optname{pdfpagerange} after the
+% |\begin{document}| or to ask \LaTeX\ to do that on your behalf:
+%
+% \begin{verbatim}
+% \AtBeginDocument{%
+% \hypersetup{%
+% pdfnumpages={\ref*{TotPages}},
+% pdfpagerange={1-\ref*{TotPages}}
+% }%
+% }
+% \end{verbatim}
+%
+%
+% \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}{1}
+% \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.
+%
+%
+% \subsection{Initial preparation}
+% \label{sec:initial-prep}
+%
+% \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}
+% \begin{macro}{\hyxmp@driver}
+% The |\hyxmp@at@end| macro includes code at the end of the document.
+% For \pdfTeX, the standard |\AtEndDocument| works well enough. For all
+% the other backends we use |\AtEndDvi| from the \pkgname{atenddvi}
+% package, which is more robust but requires an addition \LaTeX\ run.
+% \begin{macrocode}
+\def\hyxmp@driver{hpdftex}
+\ifx\hyxmp@driver\Hy@driver
+ \let\hyxmp@at@end=\AtEndDocument
+\else
+ \RequirePackage{atenddvi}
+ \let\hyxmp@at@end=\AtEndDvi
+\fi
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Integration with \textsf{hyperref}}
+%
+% An important design decision underlying \pkgname{hyperxmp} is that the
+% package should integrate seamlessly with \pkgname{hyperref}. To that
+% end, \pkgname{hyperxmp} takes its \acro{XMP} metadata from
+% \pkgname{hyperref}'s \optname{baseurl}, \optname{pdfauthor},
+% \optname{pdfkeywords}, \optname{pdflang}, \optname{pdfproducer},
+% \optname{pdfsubject}, 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{ifxetex} for detecting \XeTeX, and \pkgname{ifmtarg} for
+% testing if a macro argument is empty or all spaces.
+% \begin{macrocode}
+\RequirePackage{kvoptions}
+\RequirePackage{pdfescape}
+\RequirePackage{stringenc}
+\RequirePackage{intcalc}
+\RequirePackage{ifxetex}
+\RequirePackage{ifmtarg}
+% \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}{\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}{\@pdfapart}
+% Prepare to store the \acro{PDF/A} part ID, which defaults to~``1''.
+% \begin{macrocode}
+\def\@pdfapart{1}
+\define@key{Hyp}{pdfapart}{\hyxmp@pdfstringdef\@pdfapart{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfaconformance}
+% Prepare to store the \acro{PDF/A} conformance ID, which defaults to~``B''.
+% \begin{macrocode}
+\def\@pdfaconformance{B}
+\define@key{Hyp}{pdfaconformance}{\hyxmp@pdfstringdef\@pdfaconformance{#1}}
+% \end{macrocode}
+% \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{\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 \acro{UUID} that represents the current version of
+% the document.
+% \begin{macrocode}
+\def\@pdfversionid{}
+\define@key{Hyp}{pdfversionid}{\hyxmp@pdfstringdef\@pdfversionid{#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}{\@pdfsubtitle}
+% Prepare to store the document's subtitle.
+% \begin{macrocode}
+\def\@pdfsubtitle{}
+\define@key{Hyp}{pdfsubtitle}{\hyxmp@pdfstringdef\@pdfsubtitle{#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@suppress@pdf@metadata}
+% Suppress \pkgname{hyperref} from writing \pdfterm{Author},
+% \pdfterm{Title}, \pdfterm{Subject}, and other \acro{PDF} metadata into
+% the \pdfterm{Info} dictionary. This prevents conflicts between the
+% \acro{PDF} metadata and the \acro{XMP} metadata, which 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}
+% \begin{macrocode}
+\def\hyxmp@suppress@pdf@metadata{%
+ \global\let\PDF@FinishDoc=\@empty
+}
+\define@key{Hyp}{keeppdfinfo}[true]{%
+ \gdef\hyxmp@suppress@pdf@metadata{}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \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}
+% \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}
+% \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}{%
+ \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@find@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@find@metadata}{%
+ \edef\hyxmp@concated@metadata{%
+ \@baseurl
+ \@pdfauthor
+ \@pdfauthortitle
+ \@pdfbookedition
+ \@pdfbytes
+ \@pdfcaptionwriter
+ \@pdfcontactaddress
+ \@pdfcontactcity
+ \@pdfcontactcountry
+ \@pdfcontactemail
+ \@pdfcontactphone
+ \@pdfcontactpostcode
+ \@pdfcontactregion
+ \@pdfcontacturl
+ \@pdfcopyright
+ \@pdfcreationdate
+ \@pdfdatetime
+ \@pdfdoi
+ \@pdfeissn
+ \@pdfisbn
+ \@pdfissn
+ \@pdfissuenum
+ \@pdfkeywords
+ \@pdflang
+ \@pdflicenseurl
+ \@pdfmetadatetime
+ \@pdfmoddate
+ \@pdfnumpages
+ \@pdfpagerange
+ \@pdfpublication
+ \@pdfpubtype
+ \@pdfsubject
+ \@pdfsubtitle
+ \@pdftitle
+ \@pdftype
+ \@pdfurl
+ \@pdfversionid
+ \@pdfvolumenum
+ }%
+ \ifx\hyxmp@concated@metadata\@empty
+ \PackageWarningNoLine{hyperxmp}{%
+ \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}
+%
+% Rather than load \pkgname{hyperref} ourself we let the author do it
+% then verify he actually did. This approach gives the author the
+% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
+% either order and to call |\hypersetup| anywhere in the document's
+% preamble, not just before \pkgname{hyperxmp} is loaded.
+% \begin{macrocode}
+\AtBeginDocument{%
+ \@ifpackageloaded{hyperref}{%
+% \end{macrocode}
+% In older versions of \pkgname{hyperref}, |\@pdflang| is set to
+% |\@empty| if \optname{pdflang} is not specified. In newer versions of
+% \pkgname{hyperref}, |\@pdflang| is set to |\relax| if
+% \optname{pdflang} is not specified. The latter is a bit problematic
+% for \pkgname{hyperxmp} because it makes |\@pdflang| non-expandable,
+% which causes a literal ``|\@pdflang|'' to be written as \acro{XMP}
+% metadata. To avoid that situation we redefine |\@pdflang| as
+% |\@empty| if we see it set to |\relax|.
+% \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}
+ \ifx\@pdflang\relax
+ \let\@pdflang=\@empty
+ \fi
+% \end{macrocode}
+% If the author explicitly specified the language to use for the
+% document's metadata, we use that. If not, we use the document
+% language, specified to \pkgname{hyperref} with the \protect\optname{pdflang}
+% option. If the author did not specify a language, we use |x-default|
+% as the metadata language.
+% \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\texttt{x-default}. This addresses a bug report by Niklas
+% Beisert}
+% \begin{macrocode}
+ \ifx\@pdfmetalang\@empty
+ \ifx\@pdflang\@empty
+ \let\@pdfmetalang=\hyxmp@x@default
+ \else
+ \edef\@pdfmetalang{\@pdflang}%
+ \fi
+ \fi
+ \hyxmp@xmlify\@pdfmetalang
+% \end{macrocode}
+% If the author explicitly specified the document date, override the
+% compilation timestamp with the specified date.
+% \begin{macrocode}
+ \ifx\@pdfdatetime\@empty
+ \else
+ \edef\hyxmp@today{\@pdfdatetime}%
+ \fi
+% \end{macrocode}
+% If the author left \optname{pdftitle} blank but specified |\title|,
+% use the title for \optname{pdftitle}. Likewise, if the author left
+% \optname{pdfauthor} blank but specified |\author|, use the author for
+% \optname{pdfauthor}.
+% \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}
+% \begin{macrocode}
+ \@ifmtargexp{\@pdftitle}{%
+ \@ifnotmtargexp{\@title}{%
+ \hypersetup{pdftitle={\@title}}%
+ }%
+ }%
+ {}%
+ \@ifmtargexp{\@pdfauthor}{%
+ \@ifnotmtargexp{\@author}{%
+ \hypersetup{pdfauthor={\@author}}%
+ }%
+ }%
+ {}%
+% \end{macrocode}
+% Older versions of \pkgname{hyperref} write the \pdfterm{Info}
+% dictionary to the \acro{PDF} file at the end of the document. New
+% 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@suppress@pdf@metadata} at the beginning of the
+% document, for compatibility with both newer and older versions of
+% \protect\pkgname{hyperref}}
+% \begin{macrocode}
+ \hyxmp@suppress@pdf@metadata
+% \end{macrocode}
+% We wait until the end of the document to construct the \acro{XMP}
+% packet and write it to the \acro{PDF} document catalog. This gives
+% the author ample opportunity to provide metadata to \pkgname{hyperref}
+% and thereby \pkgname{hyperxmp}.
+% \begin{macrocode}
+ \hyxmp@at@end{%
+ \hyxmp@find@metadata
+ \hyxmp@embed@packet
+ }%
+ }{%
+ \PackageWarningNoLine{hyperxmp}{%
+ \jobname.tex failed to include a\MessageBreak
+ \string\usepackage\string{hyperref\string}
+ in the preamble.\MessageBreak
+ Consequently, all hyperxmp functionality will be\MessageBreak
+ disabled}%
+ }%
+}
+% \end{macrocode}
+%
+%
+% \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}); trim
+% spaces off the ends of strings (Section~\ref{sec:trim-spaces}); and,
+% in Section~\ref{sec:text-xml}, convert text to \acro{XML} (e.g.,~from
+% |<scott+hyxmp@pakin.org>| to |&lt;scott+hyxmp@pakin.org&gt;|).
+%
+% \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\ifx\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@define}
+% Use \tex\ primitives to define a given macro as today's date in
+% \textsc{yyyy}-\textsc{mm}-\textsc{dd}|T|hh|:|mm 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}
+% \begin{macrocode}
+\def\hyxmp@today@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}
+ \@tempcnta=\time
+ \divide\@tempcnta by 60%
+ \ifnum\@tempcnta<10%
+ \xdef#1{#1T0\the\@tempcnta}%
+ \else
+ \xdef#1{#1T\the\@tempcnta}%
+ \fi
+ \multiply\@tempcnta by -60%
+ \advance\@tempcnta by \time
+ \ifnum\@tempcnta<10%
+ \xdef#1{#1:0\the\@tempcnta}%
+ \else
+ \xdef#1{#1:\the\@tempcnta}%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@today}
+% Define |\hyxmp@today| 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}
+% \begin{macrocode}
+\@ifundefined{pdffeedback}{%
+ \@ifundefined{pdfcreationdate}{%
+% \end{macrocode}
+% Case 1: Neither |\pdffeedback| nor |\pdfcreationdate| is defined
+% (\XeLaTeX\ and regular \LaTeX).
+% \begin{macrocode}
+ \hyxmp@today@define\hyxmp@today
+ }{%
+% \end{macrocode}
+% Case 2: |\pdfcreationdate| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
+% \begin{macrocode}
+ \edef\hyxmp@today{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate}%
+ }%
+}{%
+% \end{macrocode}
+% Case 3: |\pdffeedback| is defined (\LuaLaTeX~0.85+).
+% \begin{macrocode}
+ \edef\hyxmp@today{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate}%
+}
+% \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}{\hyxmp@reencode}
+% This is now a placeholder macro needed only for |\@pdfmetalang| in
+% the |\begin{document}|.
+% \changes{v1.3}{2011/04/25}{Introduced this macro to re-encode Unicode
+% strings as 8-bit strings before manipulating them into \acro{XMP}
+% schema. This change addresses a bug reported by Martin M\"unch}
+% \changes{v2.0}{2012/08/02}{Replaced with an empty macro by Heiko Oberdiek}
+% \begin{macrocode}
+\newcommand*{\hyxmp@reencode}[1]{}
+% \end{macrocode}
+% \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{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 ``|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 |\@tempcnta| with the contents modulo~|#1|.
+% Note that |\@tempcntb| is overwritten in the process.
+% \begin{macrocode}
+\def\hyxmp@modulo@a#1{%
+ \@tempcntb=\@tempcnta
+ \divide\@tempcntb by #1
+ \multiply\@tempcntb by #1
+ \advance\@tempcnta 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{%
+ \@tempcnta=\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\@tempcnta} \leftarrow 3
+% \cdot \mathtt{\string\@tempcnta} + 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\@tempcnta by 3
+ \advance\@tempcnta 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 |\@tempcnta|
+% and |\@tempcntb| are overwritten in the process.
+% \begin{macrocode}
+\def\hyxmp@set@rand@num{%
+ \@tempcnta=\hyxmp@rand@num
+ \multiply\@tempcnta by 3
+ \advance\@tempcnta by \hyxmp@big@prime@ii
+ \hyxmp@modulo@a{\hyxmp@big@prime}%
+ \xdef\hyxmp@rand@num{\the\@tempcnta}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@append@hex}
+% Append a randomly selected hexadecimal digit to macro~|#1|. Note that
+% both |\@tempcnta| and |\@tempcntb| are overwritten in the process.
+% \begin{macrocode}
+\def\hyxmp@append@hex#1{%
+ \hyxmp@set@rand@num
+ \@tempcnta=\hyxmp@rand@num
+ \hyxmp@modulo@a{16}%
+ \ifnum\@tempcnta<10
+ \xdef#1{#1\the\@tempcnta}%
+ \else
+% \end{macrocode}
+% There \emph{must} be a better way to handle the numbers~10--15 than
+% with |\ifcase|.
+% \begin{macrocode}
+ \advance\@tempcnta by -10
+ \ifcase\@tempcnta
+ \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 |\@tempcnta| 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
+ \@tempcnta=\hyxmp@rand@num
+ \hyxmp@modulo@a{4}%
+ \ifcase\@tempcnta
+ \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{\jobname:\@pdftitle:\@pdfauthor:}%
+ \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
+ \edef\hyxmp@rand@num{\the\@tempcnta}%
+ \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@define{\hyxmp@seed@string}%
+ \edef\hyxmp@seed@string{%
+ \jobname:\@pdftitle:\@pdfauthor:\hyxmp@today:\hyxmp@seed@string
+ }%
+ \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
+ \edef\hyxmp@rand@num{\the\@tempcnta}%
+ \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: Adobe \acro{PDF}
+% (Section~\ref{sec:adobe-pdf}), Dublin Core
+% (Section~\ref{sec:dublin-core}), \acro{XMP} Rights Management
+% (Section~\ref{sec:xmp-rights}), \acro{XMP} Media Management
+% (Section~\ref{sec:xmp-media}), \acro{XMP} Basic
+% (Section~\ref{sec:xmp-basic}), Photoshop
+% (Section~\ref{sec:photoshop}), \acro{IPTC} Photo Metadata
+% (Section~\ref{sec:photo-meta}), and \acro{PDF/A} Identification
+% (Section~\ref{sec:pdfa-id}). 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
+ \@tempcnta=0
+ \ifhyxmp@unicodetex
+ \@tempcntb=65536%
+ \else
+ \@tempcntb=256%
+ \fi
+ \loop
+ \lccode\@tempcnta=\@tempcnta
+ \advance\@tempcnta by 1
+ \ifnum\@tempcnta<\@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 |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{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 \acro{PDF/A}-1b 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\acro{PDF/A}-1b compliance}
+% \begin{macrocode}
+ \hyxmp@add@simple@var{pdf:Keywords}{@pdfkeywords}%
+ \hyxmp@add@simple@var{pdf:Producer}{@pdfproducer}%
+ \@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}
+ \hyxmp@add@simple{pdf:PDFVersion}{1.\the\pdfminorversion}%
+ }%
+ }{%
+% \end{macrocode}
+% Case 3: |\pdfvariable| is defined (\LuaLaTeX~0.85+).
+% \begin{macrocode}
+ \hyxmp@add@simple{pdf:PDFVersion}{1.\the\pdfvariable minorversion}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \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}
+% \begin{macrocode}
+\newcommand*{\hyxmp@add@simple}[2]{%
+ \@ifnotmtargexp{#2}{%
+ \hyxmp@xmlify{#2}%
+ \hyxmp@add@to@xml{%
+ \hyxmp@extra@indent______<#1>\hyxmp@xmlified</#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[]}%
+}
+% \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}
+%
+%
+% \subsubsection{The Dublin Core schema}
+% \label{sec:dublin-core}
+%
+% \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 \texttt{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}
+% \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%
+ }%
+ \ifx\@pdfmetalang\hyxmp@x@default
+ \else
+ \hyxmp@xmlify{\@pdfmetalang}%
+ \hyxmp@add@to@xml{%
+__________<rdf:li xml:lang="\hyxmp@xmlified">\hyxmp@value</rdf:li>^^J%
+ }%
+ \fi
+ \hyxmp@add@to@xml{%
+__________<rdf:li xml:lang="\hyxmp@x@default">\hyxmp@value</rdf:li>^^J%
+ }%
+% \end{macrocode}
+% Include variants of the text expressed in other languages, as specified by
+% the author using |\XMPLangAlt| (Section~\ref{sec:lang-alt}).
+% \begin{macrocode}
+ \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
+% \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]{%
+ \@ifnotmtarg{#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@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}, and the \xmpprop{dc:language} property if the
+% author specified \optname{pdflang}. We also specify the
+% \xmpprop{dc:date} property using the date the document was run through
+% \LaTeX\ and the \xmpprop{dc:source} property using the base name of
+% the source file with |.tex| appended.
+% \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}
+% \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}%
+ \hyxmp@singleton@dc[Seq]{date}{\hyxmp@today}%
+ \hyxmp@singleton@dc{language}{\@pdflang}%
+ \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
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{The XMP Rights Management schema}
+% \label{sec:xmp-rights}
+%
+% \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}
+%
+%
+% \subsubsection{The XMP Media Management schema}
+% \label{sec:xmp-media}
+%
+% \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{%
+ \@ifmtargexp{\hyxmp@DocumentID}{\hyxmp@def@DocumentID}{}%
+ \@ifmtargexp{\hyxmp@InstanceID}{\hyxmp@def@InstanceID}{}%
+ \hyxmp@add@simple{xmpMM:DocumentID}{\hyxmp@DocumentID}%
+ \hyxmp@add@simple{xmpMM:InstanceID}{\hyxmp@InstanceID}%
+ \hyxmp@add@simple{xmpMM:VersionID}{\@pdfversionid}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The XMP Basic schema}
+% \label{sec:xmp-basic}
+%
+% \begin{macro}{\hyxmp@define@createdate}
+% \begin{macro}{\hyxmp@createdate}
+% Define |\hyxmp@createdate| as the document's creation date but in
+% \acro{XMP} date format, not \acro{PDF} date format. We use
+% |\hyxmp@createdate| for the \xmpprop{xmp:CreateDate},
+% \xmpprop{xmp:ModifyDate}, and \xmpprop{xmp:MetadataDate} fields.
+% \begin{macrocode}
+\newcommand*{\hyxmp@define@createdate}{%
+ \@ifundefined{pdffeedback}{%
+ \@ifundefined{pdfcreationdate}{%
+% \end{macrocode}
+% Case 1: Neither |\pdffeedback| nor |\pdfcreationdate| is defined
+% (\XeLaTeX\ and regular \LaTeX).
+% \begin{macrocode}
+ \hyxmp@today@define\hyxmp@createdate
+ }{%
+% \end{macrocode}
+% Case 2: |\pdfcreationdate| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
+% \begin{macrocode}
+ \edef\hyxmp@createdate{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate}%
+ }%
+ }{%
+% \end{macrocode}
+% Case 3: |\pdffeedback| is defined (\LuaLaTeX~0.85+).
+% \begin{macrocode}
+ \edef\hyxmp@createdate{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \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}{%
+ \hyxmp@define@createdate
+% \end{macrocode}
+% For the document's creation date, use the user-specified
+% |\@pdfcreationdate| if defined and non-empty. Otherwise use our
+% fabricated |\hyxmp@createdate|.
+% \begin{macrocode}
+ \@ifundefined{@pdfcreationdate}{%
+ \hyxmp@add@simple{xmp:CreateDate}{\hyxmp@createdate}%
+ }{%
+ \ifx\@pdfcreationdate\@empty
+ \hyxmp@add@simple{xmp:CreateDate}{\hyxmp@createdate}%
+ \else
+ \hyxmp@add@simple{xmp:CreateDate}{%
+ \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfcreationdate}}%
+ \fi
+ }%
+% \end{macrocode}
+% For the document's modification date, use the user-specified
+% |\@pdfmoddate| if defined and non-empty. Otherwise use our
+% fabricated |\hyxmp@createdate|.
+% \begin{macrocode}
+ \@ifundefined{@pdfmoddate}{%
+ \hyxmp@add@simple{xmp:ModifyDate}{\hyxmp@createdate}%
+ }{%
+ \ifx\@pdfmoddate\@empty
+ \hyxmp@add@simple{xmp:ModifyDate}{\hyxmp@createdate}%
+ \else
+ \hyxmp@add@simple{xmp:ModifyDate}{%
+ \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfmoddate}}%
+ \fi
+ }%
+% \end{macrocode}
+% For the document's metadata date, use the user-specified
+% |\@pdfmetadatetime| if defined and non-empty. Otherwise use our
+% fabricated |\hyxmp@createdate|.
+% \begin{macrocode}
+ \ifx\@pdfmetadatetime\@empty
+ \hyxmp@add@simple{xmp:MetadataDate}{\hyxmp@createdate}%
+ \else
+ \hyxmp@add@simple{xmp:MetadataDate}{\@pdfmetadatetime}%
+ \fi
+% \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}
+%
+%
+% \subsubsection{The Photoshop schema}
+% \label{sec: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}
+%
+%
+% \subsubsection{The PDF/A Identification schema}
+% \label{sec:pdfa-id}
+%
+% \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 \acro{PDF/A}-1b 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}
+%
+%
+% \subsubsection{The IPTC Photo Metadata schema}
+% \label{sec:photo-meta}
+%
+% \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 it 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}
+%
+% \subsubsection{The PRISM Basic Metadata schema}
+% \label{sec:prism-meta}
+%
+% \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}
+%
+% \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}
+% Define |\hyxmp@iptc@data| as the concatenation of all \acro{IPTC}
+% photo metadata supplied by the document.
+% \begin{macrocode}
+\newcommand*{\hyxmp@check@iptc@data}{%
+% \end{macrocode}
+% \begin{macro}{\hyxmp@iptc@data}
+% \begin{macrocode}
+ \edef\hyxmp@iptc@data{%
+ \@pdfcontactaddress
+ \@pdfcontactcity
+ \@pdfcontactregion
+ \@pdfcontactpostcode
+ \@pdfcontactcountry
+ \@pdfcontactphone
+ \@pdfcontactemail
+ \@pdfcontacturl
+ }%
+}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@check@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}{%
+% \end{macrocode}
+% \begin{macro}{\hyxmp@prism@data}
+% \begin{macrocode}
+ \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@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}
+% \begin{macrocode}
+\newcommand{\hyxmp@declare@property}[4][Text]{%
+ \hyxmp@add@to@xml{%
+________________<rdf:li rdf:parseType="Resource">^^J%
+__________________<pdfaProperty:name>#2</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@mm@extensions}
+% Declare the \acro{XMP} Media Management schema.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+% \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@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@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/2.1/}%
+ \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@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 \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@mm@extensions
+ \fi
+% \end{macrocode}
+% 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}
+% \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:prism="http://prismstandard.org/namespaces/basic/2.1/"^^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@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@mm@schema
+ \hyxmp@iptc@schema
+ \hyxmp@prism@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
+ \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\@tempcnta
+ >>
+ stream^^J\hyxmp@xml endstream%
+ }%
+ \special{pdf: docview
+ <<
+ /Metadata @hyxmp@Metadata
+ >>
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@string@len}
+% Set |\@tempcnta| 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]{%
+ \@tempcnta=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\@tempcnta by -1
+ \else
+ \advance\@tempcnta 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\@tempcnta 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}
+%
+% 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}
+%
+% \Finale
+\endinput