From 7ffadf39bd1a52617123fde2be7534b63fa288d8 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 4 May 2011 23:41:46 +0000 Subject: hyperxmp (3may11) git-svn-id: svn://tug.org/texlive/trunk@22306 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/source/latex/hyperxmp/hyperxmp.dtx | 493 +++++++++++++-------- 1 file changed, 319 insertions(+), 174 deletions(-) (limited to 'Master/texmf-dist/source/latex/hyperxmp') diff --git a/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx b/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx index fb028cb5a79..2cc3ff17731 100644 --- a/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx +++ b/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx @@ -22,7 +22,7 @@ %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{hyperxmp} %<*package> - [2011/04/17 v1.2 Store hyperref metadata in XMP format] + [2011/04/30 v1.3 Store hyperref metadata in XMP format] % % %<*driver> @@ -30,7 +30,7 @@ \usepackage{graphicx} \usepackage{tocbibind} \usepackage{hyperxmp} -\usepackage[bookmarksopen]{hyperref} +\usepackage[bookmarksopen,bookmarksopenlevel=2,pdflang=en]{hyperref} \EnableCrossrefs \CodelineIndex \RecordChanges @@ -42,7 +42,7 @@ % % \fi % -% \CheckSum{834} +% \CheckSum{872} % % \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 @@ -65,8 +65,8 @@ % % \GetFileInfo{hyperxmp.dtx} % -% \DoNotIndex{\#,\&,\<,\>,\\,\_,\|,\ } -% \DoNotIndex{\@cons,\@elt,\@empty,\@ifpackageloaded,\@ifundefined} +% \DoNotIndex{\#,\&,\<,\>,\^,\\,\_,\|,\ } +% \DoNotIndex{\@cons,\@empty,\@ifpackageloaded,\@ifundefined} % \DoNotIndex{\@tempcnta,\@tempcntb} % \DoNotIndex{\advance,\afterassignment,\aftergroup} % \DoNotIndex{\begingroup,\bgroup} @@ -87,21 +87,29 @@ % % ^^A Define a few logical styles. % \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}} -% \DeclareRobustCommand{\pkgname}[1]{\textsf{#1}\SortIndex{#1}{\textsf{#1}}} -% \DeclareRobustCommand{\xmpterm}[1]{\textsf{#1}\SortIndex{#1}{\textsf{#1}}} -% \DeclareRobustCommand{\pdfterm}[1]{\textsf{#1}\SortIndex{#1}{\textsf{#1}}} -% \DeclareRobustCommand{\cmdname}[1]{\texttt{#1}\SortIndex{#1}{\texttt{#1}}} +% \DeclareRobustCommand{\pkgname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}} +% \DeclareRobustCommand{\xmpterm}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}} +% \DeclareRobustCommand{\pdfterm}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}} +% \DeclareRobustCommand{\cmdname}[1]{\mbox{\texttt{#1}}\SortIndex{#1}{\texttt{#1}}} % \DeclareRobustCommand{\acrostyle}[1]{\textsc{\MakeLowercase{#1}}} % \DeclareRobustCommand{\acro}[1]{^^A -% \acrostyle{#1}^^A +% \mbox{\acrostyle{#1}}^^A % \SortIndex{#1}{\acrostyle{#1}}^^A % } +% +% ^^A Define some other shortcut macros. % \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 +% } % % ^^A Specify this document's metadata. % \title{The \pkgname{hyperxmp} package\thanks{This document @@ -113,7 +121,8 @@ % pdfsubject={LaTeX2e support for XMP metadata}, % pdfkeywords={LaTeX, embedded metadata, XMP, PDF, copyright, license, comments}, % pdfcopyright={Copyright (C) 2011, Scott Pakin}, -% pdflicenseurl={http://www.latex-project.org/lppl/} +% pdflicenseurl={http://www.latex-project.org/lppl/}, +% pdfcaptionwriter={Scott Pakin} % } % % \maketitle @@ -130,15 +139,15 @@ % % \section{Introduction} % -% Adobe Systems, Inc.\ has recently been promoting -% \acro{XMP}~\cite{Adobe2005:XMP}---eXtensible Metadata Platform---as a +% Adobe Systems, Inc.\ has been promoting +% \acro{XMP}~\cite{Adobe2010: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 of \acro{PDF}, \acrostyle{JPEG}, -% \acrostyle{HTML}, or any other type, it is trivial for a program (or +% 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. % @@ -165,12 +174,12 @@ % % In the preceding code, the |dc| namespace refers to the % \href{http://purl.org/DC/}{Dublin Core schema}, a collection of -% metadata properties. The |dc:creator| property surrounds the list of -% authors. The |rdf| namespace is the +% metadata properties. The \xmpterm{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 |rdf:Seq| as an ordered list of values. Each author is -% represented by an individual list item (|rdf:li|), making it easy for -% an \acro{XML} parser to separate the authors' names. +% 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 @@ -178,27 +187,29 @@ % document. % % \paragraph{What metadata does \textsf{hyperxmp} process?} -% \pkgname{hyperxmp} knows how to embed each of the following types of +% \pkgname{hyperxmp} knows how to embed all of the following types of % metadata within a document: % % \begin{itemize} -% \item authors (|dc:creator|) -% \item copyright (|dc:rights|) -% \item date (|dc:date|) -% \item document identifier (|xapMM:DocumentID|) -% \item document instance identifier (|xapMM:InstanceID|) -% \item format (|dc:format|) -% \item keywords (|pdf:Keyword| and |dc:subject|) -% \item license \acro{URL} (|xapRights:WebStatement|) -% \item \acro{PDF}-generating tool (|pdf:Producer|) -% \item summary (|dc:description|) -% \item title (|dc:title|) +% \item authors (\xmpterm{dc:creator}) +% \item copyright (\xmpterm{dc:rights}) +% \item date (\xmpterm{dc:date}) +% \item document identifier (\xmpterm{xapMM:DocumentID}) +% \item document instance identifier (\xmpterm{xapMM:InstanceID}) +% \item format (\xmpterm{dc:format}) +% \item keywords (\xmpterm{pdf:Keyword} and \xmpterm{dc:subject}) +% \item license \acro{URL} (\xmpterm{xapRights:WebStatement}) +% \item metadata writer (\xmpterm{photoshop:CaptionWriter}) +% \item \acro{PDF}-generating tool (\xmpterm{pdf:Producer}) +% \item primary author's position/title (\xmpterm{photoshop:AuthorsPosition}) +% \item summary (\xmpterm{dc:description}) +% \item title (\xmpterm{dc:title}) % \end{itemize} % % \noindent % More types of metadata may be added in a future release. % -% \paragraph{How does \textsf{hyperxmp} compare with the \textsf{xmpincl} +% \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 @@ -228,11 +239,12 @@ % construct its \acro{XMP} data using the following \pkgname{hyperref} options: % % \begin{itemize} -% \item |pdfauthor|, -% \item |pdfkeywords|, -% \item |pdfproducer|, -% \item |pdfsubject|, and -% \item |pdftitle|. +% \item |pdfauthor| +% \item |pdfkeywords| +% \item |pdflang| +% \item |pdfproducer| +% \item |pdfsubject| +% \item |pdftitle| % \end{itemize} % % \noindent @@ -240,13 +252,27 @@ % following options, which have meaning only to \pkgname{hyperxmp}: % % \begin{itemize} -% \item |pdfcopyright| and -% \item |pdflicenseurl|. +% \item |pdfauthortitle| +% \item |pdfcaptionwriter| +% \item |pdfcopyright| +% \item |pdflicenseurl| +% \item |pdfmetalang| % \end{itemize} % % \noindent -% |\pdfcopyright| defines the copyright text. |pdflicenseurl| defines a -% \acro{URL} that points to the document's license agreement. +% |pdfauthortitle| indicates the primary author's position or title. +% |pdfcaptionwriter| specifies the name of the person who added +% the metadata to the document. |\pdfcopyright| defines the copyright +% text. |pdflicenseurl| identifies a \acro{URL} that points to the +% document's license agreement. |pdfmetalang| indicates the natural +% language in which the metadata is written, typically as 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 |pdfmetalang| is not specified, +% \pkgname{hyperxmp} assumes the metadata language is the same as the +% document language (\pkgname{hyperref}'s |pdflang| option). If neither +% |pdfmetalang| nor |pdflang| is specified, \pkgname{hyperxmp} uses +% ``|x-default|'' as the metadata language. % % It's usually more convenient to provide values for those options using % \pkgname{hyperref}'s |\hypersetup| command than on the |\usepackage| @@ -271,7 +297,8 @@ % pdfauthor={Albert Einstein}, % pdfcopyright={Copyright (C) 1905, Albert Einstein}, % pdfsubject={photoelectric effect}, -% pdfkeywords={energy quanta, Hertz effect, quantum physics} +% pdfkeywords={energy quanta, Hertz effect, quantum physics}, +% pdflang={en} % } % \begin{document} % \maketitle @@ -286,21 +313,13 @@ % % \begin{itemize} % \item pdf\LaTeX +% \item Lua\LaTeX % \item \LaTeX~$+$ Dvipdfm % \item \LaTeX~$+$ Dvips~$+$ Ghostscript +% \item \LaTeX~$+$ Dvips~$+$ Adobe Acrobat Distiller +% \item \XeLaTeX % \end{itemize} % -% The combination \LaTeX~$+$ Dvips~$+$ Adobe Acrobat Distiller -% \emph{almost} works but is hampered by a Distiller bug (at least in -% version~7.0.5) that incorrectly replaces the first author with the -% complete list of authors in the generated \acro{PDF} file. That is, -% if a document's authors are Jack Napier, Edward Nigma, and Harvey -% Dent, Distiller replaces ``Jack Napier'' with a single author named -% ``Jack Napier, Edward Nigma, Harvey Dent'' and leaves ``Edward Nigma'' -% and ``Harvey Dent'' as the second and third authors, respectively. -% Until Adobe fixes this bug, Adobe Acrobat Distiller is not recommended -% for use with \pkgname{hyperxmp}. -% % Besides the approaches listed above, other approaches may work as well % but have not been tested. Note that in many \TeX\ distributions % \cmdname{ps2pdf} is a convenience script that calls Ghostscript with @@ -329,19 +348,19 @@ % application/pdf % % -% On a heuristic viewpoint +% On a heuristic viewpoint % concerning the production and transformation of % light % % % % -% photoelectric effect +% photoelectric effect % % % % -% Copyright (C) 1905, +% Copyright (C) 1905, % Albert Einstein % % @@ -373,6 +392,51 @@ % % \end{verbatim} % +% \paragraph{Note~1: Acrobat \pdfterm{Author} bug} +% A bug in Adobe Acrobat---at least in versions~10.0.1 and +% earlier---causes that \acro{PDF} reader to confuse the \acro{XMP} and +% non-\acro{XMP} author lists when displaying the document's metadata. +% Specifically, the first author is displayed as the concatenated list +% of authors from the non-\acro{XMP} data (\pdfterm{Author}) while the +% remaining authors are displayed from the \acro{XMP} data +% (\xmpterm{dc:creator}). For example, suppose that a document's authors +% are Jack Napier, Edward Nigma, and Harvey Dent. When displaying the +% document properties, Adobe Acrobat replaces ``Jack Napier'' with a +% single author named ``Jack Napier, Edward Nigma, Harvey Dent'' and +% leaves ``Edward Nigma'' and ``Harvey Dent'' as the second and third +% authors, respectively. +% +% A workaround, independent of \TeX, is to modify the \acro{PDF} file to +% remove all but the first author from the non-\acro{XMP} author list +% while retaining all of the authors in the \acro{XMP} author list. +% Doing so will cause Adobe Acrobat to properly display all of the +% authors but at the cost of other \acro{PDF} readers likely displaying +% only the first author. The following Perl command (which should be +% entered as a single line) automates this modification: +% +% \begin{verbatim} +% perl -i -ne 's,(/Author\s*\([^\,\)]+)(.*?)\),"$1)" . " " x length($2),ge; +% print' myfile.pdf +% \end{verbatim} +% +% \noindent +% (Systems with different quoting conventions from Linux/Unix may need +% to adapt the preceding commands as appropriate.) +% +% +% \paragraph{Note~2: \XeLaTeX\ object compression} +% \XeLaTeX\ (or, more precisely, the \cmdname{xdvipdfmx} back end), +% 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. Either use a different program +% (e.g.,~Lua\LaTeX) or use \XeLaTeX\ to produce a \acro{DVI} or +% \acro{XDV} file and run \cmdname{xdvipdfmx} manually on that file +% using the |-z0| option to turn off all compression (which will of +% course make the \acro{PDF} file substantially larger). +% +% +% \paragraph{Note~3: Literal commas} % \pkgname{hyperxmp} splits the |pdfauthor| and |pdfkeywords| lists at % commas. Therefore, when specifying |pdfauthor| and |pdfkeywords|, you % should separate items with commas. Also, omit ``|and|'' and other @@ -407,25 +471,25 @@ % % \StopEventually{^^A % \begin{thebibliography}{1} -% \bibitem{Adobe2004:PDF} +% \bibitem{Adobe2010:pdfmark} % Adobe Systems, Inc., San Jose, California. -% \newblock {\em {PDF} Reference, Fifth Edition: {A}dobe Portable Document Format -% Version~1.6}, November 2004. +% \newblock {\em {A}dobe {A}crobat~{X} {SDK} Help, pdfmark Reference}. % \newblock Available from -% \url{http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf}. +% \url{http://www.adobe.com/devnet/acrobat/documentation.html}. % -% \bibitem{Adobe2005:pdfmark} +% \bibitem{Adobe2008:PDF} % Adobe Systems, Inc., San Jose, California. -% \newblock {\em {A}dobe {A}crobat~7.0.5 pdfmark Reference Manual}, October~2, -% 2005. -% \newblock Available from -% \url{http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/pdf_creation_apis_and_specs/pdfmarkReference.pdf}. +% \newblock {\em 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{Adobe2005:XMP} +% \bibitem{Adobe2010:XMP} % Adobe Systems, Inc., San Jose, California. -% \newblock {\em {XMP} Specification}, June 2005. +% \newblock {\em {XMP} Specification Part~1: Data model, Serialization, and Core +% Properties}, July 2010. % \newblock Available from -% \url{http://partners.adobe.com/public/developer/en/xmp/sdk/xmpspecification.pdf}. +% \url{http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart1.pdf}. % % \bibitem{Downes1994:ATB15} % Michael Downes. @@ -434,6 +498,12 @@ % January~3, 1994. % \newblock Archived by Google at % \url{http://groups.google.com/group/comp.text.tex/msg/7da7643b9e8f3b48}. +% +% \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}. % \end{thebibliography} % } % @@ -456,8 +526,8 @@ % ``\,{\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|, mark the character as -% category code~12 (``other''), and restore the original category code +% 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`\"} @@ -473,18 +543,27 @@ % end, \pkgname{hyperxmp} takes its \acro{XMP} metadata from the % \pkgname{hyperref} |pdftitle|, |pdfauthor|, |pdfsubject|, and % |pdfkeywords| options plus two new options, |pdfcopyright| and -% |pdflicenseurl|, introduced by \pkgname{hyperxmp}. +% |pdflicenseurl|, introduced by \pkgname{hyperxmp}. 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 three helper packages: \pkgname{keyval} for package-option +% processing and \pkgname{pdfescape} and \pkgname{stringenc} for +% re-encoding Unicode strings. % % \begin{macrocode} \RequirePackage{keyval} +\RequirePackage{pdfescape} +\RequirePackage{stringenc} % \end{macrocode} % % \begin{macro}{\@pdfcopyright} -% Prepare to store the document's copyright statement. 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 the macro name with our package-specific |\hyxmp@| -% prefix. +% Prepare to store the document's copyright statement. % \begin{macrocode} \def\@pdfcopyright{} \define@key{Hyp}{pdfcopyright}{\pdfstringdef\@pdfcopyright{#1}} @@ -493,10 +572,7 @@ % % \begin{macro}{\@pdflicenseurl} % Prepare to store the \acro{URL} containing the document's license -% agreement. 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 the -% macro name with our package-specific |\hyxmp@| prefix. +% agreement. % \begin{macrocode} \def\@pdflicenseurl{} \define@key{Hyp}{pdflicenseurl}{\pdfstringdef\@pdflicenseurl{#1}} @@ -504,11 +580,7 @@ % \end{macro} % % \begin{macro}{\@pdfauthortitle} -% Prepare to store the author's position/title (e.g.,~Staff Writer). 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 the macro name with our -% package-specific |\hyxmp@| prefix. +% Prepare to store the author's position/title (e.g.,~Staff Writer). % \begin{macrocode} \def\@pdfauthortitle{} \define@key{Hyp}{pdfauthortitle}{\pdfstringdef\@pdfauthortitle{#1}} @@ -517,46 +589,51 @@ % % \begin{macro}{\@pdfcaptionwriter} % Prepare to store the name of the person who inserted the -% \pkgname{hyperxmp} metadata. 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 the macro name with our package-specific |\hyxmp@| prefix. +% \pkgname{hyperxmp} metadata. % \begin{macrocode} \def\@pdfcaptionwriter{} \define@key{Hyp}{pdfcaptionwriter}{\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}{\pdfstringdef\@pdfmetalang{#1}} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\hyxmp@find@metadata} +% \begin{macro}{\hyxmp@concated@metadata} % Issue a warning message if the author failed to include any metadata -% at all. +% at all. Note that we don't consider |\@pdflang| or |\@pdfmetalang| as +% metadata, as they're meaningful only when used in conjunction with +% other information. % \begin{macrocode} \newcommand*{\hyxmp@find@metadata}{% - \ifx\@pdfauthor\@empty - \ifx\@pdfcopyright\@empty - \ifx\@pdfkeywords\@empty - \ifx\@pdflicenseurl\@empty - \ifx\@pdfauthortitle\@empty - \ifx\@pdfcaptionwriter\@empty - \ifx\@pdfsubject\@empty - \ifx\@pdftitle\@empty - \PackageWarningNoLine{hyperxmp}{% + \edef\hyxmp@concated@metadata{% + \@pdfauthor + \@pdfauthortitle + \@pdfcaptionwriter + \@pdfcopyright + \@pdfkeywords + \@pdflicenseurl + \@pdfsubject + \@pdftitle + }% + \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 hyperxmp\MessageBreak documentation for instructions on how to provide\MessageBreak -metadata values to hyperxmp% - }% - \fi - \fi - \fi - \fi - \fi - \fi - \fi +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 @@ -568,6 +645,26 @@ metadata values to hyperxmp% \@ifpackageloaded{hyperref}% {% % \end{macrocode} +% If the user 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 |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 \texttt{pdfmetalang} package +% option, which enables an author to specify the language in which he +% wrote the document's metadata} +% \begin{macrocode} + \ifx\@pdfmetalang\@empty + \ifx\@pdflang\@empty + \def\@pdfmetalang{x-default}% + \else + \edef\@pdfmetalang{\@pdflang}% + \fi + \fi + \ifHy@unicode + \hyxmp@reencode\@pdfmetalang + \fi +% \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} @@ -592,7 +689,7 @@ disabled}% % \subsection{Manipulating author-supplied data} % % The author provides metadata information to \pkgname{hyperxmp} via -% package options to \pkgname{hyperref} or via the \pkgname{hyperref} +% 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 @@ -784,8 +881,35 @@ disabled}% % The ``|<|'', ``|>|'', and ``|&|'' characters are significant to \acro{XML}. % We therefore need to escape them in any author-supplied text. % +% \begin{macro}{\hyxmp@reencode} +% \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} +% \begin{macro}{\hyxmp@reencoded} +% Given a control word that expands to a Unicode (|utf16be|) string, +% re-encode it in a more basic (|pdfdoc|) 8-bit encoding so we don't +% wind up escaping each octet of what should be a single 16-bit +% character. The bulk of the work is left to |\EdefUnescapeString| from +% the \pkgname{pdfescape} package and |\StringEncodingConvert| and to +% |\StringEncodingSuccessFailure| from the \pkgname{stringenc} package. +% \begin{macrocode} +\newcommand*{\hyxmp@reencode}[1]{% + \EdefUnescapeString\hyxmp@reencoded{#1}% + \StringEncodingConvert\hyxmp@reencoded\hyxmp@reencoded{utf16be}{pdfdoc}% + \StringEncodingSuccessFailure{% + \global\let\hyxmp@reencoded=\hyxmp@reencoded + }{% + \gdef\hyxmp@reencoded{#1}% + }% + \edef#1{\hyxmp@reencoded}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}{\hyxmp@xmlify} % \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~``|<|'' @@ -801,7 +925,11 @@ disabled}% % \begin{macrocode} \newcommand*{\hyxmp@xmlify}[1]{% \gdef\hyxmp@xmlified{}% - \expandafter\hyxmp@xmlify@i#1\@empty + \edef\hyxmp@text{#1}% + \ifHy@unicode + \hyxmp@reencode\hyxmp@text + \fi + \expandafter\hyxmp@xmlify@i\hyxmp@text\@empty \@ifundefined{pdfmark}{}{% \expandafter\hyxmp@obscure@spaces\expandafter{\hyxmp@xmlified}% }% @@ -809,6 +937,7 @@ disabled}% % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\hyxmp@xmlify@i} % \begin{macro}{\hyxmp@one@token} @@ -937,10 +1066,10 @@ disabled}% % \begin{macro}{\hyxmp@obscure@spaces} % The \cmdname{dvips} backend rather obnoxiously word-wraps text. Doing % so can cause \acro{XMP} metadata to be displayed incorrectly. For -% example, Adobe Acrobat displays the document's |dc:rights| (copyright -% notice) within a single-line field. By introducing an extra line -% break in the middle of the copyright notice, \cmdname{dvips} -% implicitly causes it to be truncated when displayed. +% example, Adobe Acrobat displays the document's \xmpterm{dc:rights} +% (copyright notice) within a single-line field. By introducing an +% extra line break in the middle of the copyright notice, +% \cmdname{dvips} implicitly causes it to be truncated when displayed. % % To thwart \cmdname{dvips}'s word-wrapping, we define % |\hyxmp@obscure@spaces| to replace each space in a given piece of text @@ -976,11 +1105,12 @@ disabled}% % % % \subsection{UUID generation} +% \label{sec:uuid-gen} % % We use a linear congruential generator to produce pseudorandom % \acro{UUID}s. True, this method has its flaws but it's simple to % implement in \TeX\ and is good enough for producing the \acro{XMP} -% \xmpterm{DocumentID} and \xmpterm{InstanceID} fields. +% \xmpterm{xapMM:DocumentID} and \xmpterm{xapMM:InstanceID} fields. % % \begin{macro}{\hyxmp@modulo@a} % Replace the contents of |\@tempcnta| with the contents modulo~|#1|. @@ -1170,10 +1300,13 @@ disabled}% % % \subsection{Constructing the XMP packet} % -% An \acro{XMP} packet comprises a header, ``serialized \acro{XMP}'', -% padding, and a trailer~\cite{Adobe2005:XMP}. The serialized -% \acro{XMP} includes blocks of \acro{XML} for various \acro{XMP} -% schemata: Adobe \acro{PDF} (Section~\ref{sec:adobe-pdf}), Dublin Core +% 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{Adobe2010: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}), and \acro{XMP} Media Management % (Section~\ref{sec:xmp-media}). The |\hyxmp@construct@packet| macro @@ -1215,11 +1348,11 @@ disabled}% % % \begin{macro}{\hyxmp@padding} % \begin{macro}{\hyxmp@xml} -% The \acro{XMP} specification~\cite{Adobe2005:XMP} recommends leaving a -% few kilobytes of whitespace at the end of each \acro{XMP} packet to -% facilitate editing the packet in place. |\hyxmp@padding| is defined -% to contain 32~lines of 50~spaces and a newline apiece for a total of -% 1632 characters of whitespace. +% 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{Adobe2010:XMP}. +% |\hyxmp@padding| is defined to contain 32~lines of 50~spaces and a +% newline apiece for a total of 1632 characters of whitespace. % \begin{macrocode} \bgroup \xdef\hyxmp@xml{}% @@ -1277,9 +1410,9 @@ __________________________________________________^^J% \ifx\hyxmp@have@any\@empty \else % \end{macrocode} -% Add a block of \acro{XML} to |\hyxmp@xml| that lists the document's keywords -% (the \xmpterm{Keywords} property) and the tools used to produce the -% \acro{PDF} file (the \xmpterm{Producer} property). +% Add a block of \acro{XML} to |\hyxmp@xml| that lists the document's +% keywords (the \xmpterm{pdf:Keywords} property) and the tools used to +% produce the \acro{PDF} file (the \xmpterm{pdf:Producer} property). % \begin{macrocode} \hyxmp@add@to@xml{% ______^^J% \hyxmp@add@to@xml{% _________^^J% ____________^^J% -_______________\hyxmp@xmlified^^J% +_______________\hyxmp@xmlified^^J% ____________^^J% _________^^J% }% @@ -1345,7 +1478,19 @@ _________^^J% ____________^^J% }% \bgroup - \hyxmp@commas@to@list\hyxmp@list{#3}% +% \end{macrocode} +% \begin{macro}{\hyxmp@text} +% \begin{macro}{\@elt} +% We store the comma-separated list in |\hyxmp@text| so we can re-encode +% it from Unicode if necessary. We then redefine |\@elt| to +% \acro{XML}-ify each element of the list and append it to +% |\hyxmp@xmlified|. +% \begin{macrocode} + \edef\hyxmp@text{#3}% + \ifHy@unicode + \hyxmp@reencode\hyxmp@text + \fi + \hyxmp@commas@to@list\hyxmp@list{\hyxmp@text}% \def\@elt##1{% \hyxmp@xmlify{##1}% \hyxmp@add@to@xml{% @@ -1362,16 +1507,18 @@ _________^^J% } % \end{macrocode} % \end{macro} +% \end{macro} +% \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 \xmpterm{title} property -% if the author specified a |pdftitle|, the \xmpterm{description} -% property if the author specified a |pdfsubject|, the \xmpterm{rights} +% macro. Specifically, we add entries for the \xmpterm{dc:title} property +% if the author specified a |pdftitle|, the \xmpterm{dc:description} +% property if the author specified a |pdfsubject|, the \xmpterm{dc:rights} % property if the author specified a |pdfcopyright|, the -% \xmpterm{creator} property if the author specified a |pdfauthor|, and -% the \xmpterm{subject} property if the author specified |pdfkeywords|. -% We also specify the \xmpterm{date} property using the date the +% \xmpterm{dc:creator} property if the author specified a |pdfauthor|, and +% the \xmpterm{dc:subject} property if the author specified |pdfkeywords|. +% We also specify the \xmpterm{dc:date} property using the date the % document was run through \LaTeX. % \begin{macrocode} \newcommand*{\hyxmp@dc@schema}{% @@ -1398,9 +1545,10 @@ ______^^J% % % \begin{macro}{\hyxmp@xapRights@schema} % Add properties defined by the XMP Rights Management schema to the -% |\hyxmp@xml| macro. Currently, these are only the \xmpterm{Marked} -% property and the \xmpterm{WebStatement} property and only if the -% author defined a |pdflicenseurl|. +% |\hyxmp@xml| macro. Currently, these are only the +% \xmpterm{xapRights:Marked} property and the +% \xmpterm{xapRights:WebStatement} property and only if the author +% defined a |pdflicenseurl|. % \begin{macrocode} \newcommand*{\hyxmp@xapRights@schema}{% \ifx\@pdflicenseurl\@empty @@ -1423,12 +1571,12 @@ ______^^J% % % \begin{macro}{\hyxmp@mm@schema} % Add properties defined by the XMP Media Management schema to the -% |\hyxmp@xml| macro. Although the \xmpterm{DocumentID} property is -% defined in the \acro{XMP} specification~\cite{Adobe2005:XMP}, the -% \xmpterm{InstanceID} property is not. However, an -% \xmpterm{InstanceID} field is produced by Adobe Acrobat~7.0 (the -% latest version at the time of this writing) so it's probably worth -% including here. +% |\hyxmp@xml| macro. According to the \acro{XMP} specification, the +% \xmpterm{xapMM:DocumentID} property is supposed to uniquely identify a +% document, and the \xmpterm{xapMM:InstanceID} property is supposed to +% change with each save operation~\cite{Adobe2010:XMP}. As seen in +% Section~\ref{sec:uuid-gen}, we do what we can to honor this intention +% from within a \TeX-based workflow. % \begin{macrocode} \gdef\hyxmp@mm@schema{% \hyxmp@def@DocumentID @@ -1450,14 +1598,14 @@ ______^^J% % \begin{macro}{\hyxmp@photoshop@schema} % \begin{macro}{\hyxmp@photoshop@data} % Add properties defined by the Photoshop schema to the |\hyxmp@xml| -% macro. We support only the \xmpterm{AuthorsPosition} and -% \xmpterm{CaptionWriter} properties, as that's all that Adobe Acrobat -% currently displays. +% macro. We support only the \xmpterm{photoshop:AuthorsPosition} and +% \xmpterm{photoshop:CaptionWriter} properties, as that's all that Adobe +% Acrobat currently displays. % \changes{v1.2}{2010/06/07}{Added support for the Photoshop schema} % \begin{macrocode} \gdef\hyxmp@photoshop@schema{% - \def\hyxmp@photoshop@data{\@pdfauthortitle\@pdfcaptionwriter}% - \ifx\@hyxmp@photoshop@data\@empty + \edef\hyxmp@photoshop@data{\@pdfauthortitle\@pdfcaptionwriter}% + \ifx\hyxmp@photoshop@data\@empty \else \hyxmp@add@to@xml{% ______\hyxmp@xmlified^^J% \fi % \end{macrocode} % \begin{macrocode} - \ifx\@hyxmp@photoshop@data\@empty + \ifx\hyxmp@photoshop@data\@empty \else \hyxmp@add@to@xml{% ______^^J% @@ -1499,15 +1647,13 @@ ______^^J% % % \begin{macro}{\hyxmp@construct@packet} % \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. The \acro{XMP} -% specification~\cite{Adobe2005:XMP} states that the argument to the -% \xmpterm{begin} attribute must be ``the Unicode `zero-width -% non-breaking space character'~(U+FEFF)''. However, Adobe Acrobat~7.0 -% (the latest version at the time of this writing) inserts the sequence -% \meta{EF}\meta{BB}\meta{BF} so that's what we use here. -% -% We explicitly mark characters \meta{EF}, \meta{BB}, \meta{BF} as +% Successively add \acro{XML} data to |\hyxmp@xml| until we have +% something we can insert into the document's \acro{PDF} catalog. The +% \acro{XMP} specification states that the argument to the +% \xmpterm{begin} attribute is supposed to be ``the Unicode character +% U+FEFF used as a byte-order marker''~\cite{Adobe2010:XMP}, so that's +% what we use, although inserted as the 8-bit character sequence +% \meta{EF}\meta{BB}\meta{BF}. We explicitly mark those characters as % character code~12 (``letter'') because the \pkgname{inputenc} package % re-encodes them as character code~13 (``active''), which causes % \LaTeX\ to abort with an ``\texttt{Undefined control sequence}'' error @@ -1548,11 +1694,9 @@ ___^^J% % % \subsection{Embedding the XMP packet} % -% The \acro{PDF} specification~\cite{Adobe2004:PDF} says that ``a -% metadata stream can be attached to a document through the -% \pdfterm{Metadata} entry in the document catalog'' so that's what we -% do here. \pkgname{hyperxmp} does not currently support the embedding -% of \acro{XMP} in any format other than \acro{PDF}. +% 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} @@ -1639,17 +1783,18 @@ ___^^J% Raw={\string{hyxmp@Metadata\string}}% }% % \end{macrocode} -% Adobe's |pdfmark| reference~\cite{Adobe2005:pdfmark} indicates that a -% metadata stream can be added to the document catalog by specifying the -% \pdfterm{Metadata} |pdfmark| instead of the \pdfterm{PUT} |pdfmark|. -% I see no advantage to this alternative mechanism and, furthermore, it -% works only with Adobe Acrobat Distiller and only with versions~6.0 -% onwards. Consequently, \pkgname{hyperxmp} uses the traditional -% \pdfterm{PUT} mechanism to point the document catalog to our metadata -% stream. +% Adobe's |pdfmark| reference indicates that a metadata stream should be +% added to the document catalog by specifying the \pdfterm{Metadata} +% |pdfmark|~\cite{Adobe2010:pdfmark}. However, earlier versions of +% Adobe Acrobat Distiller (pre-6.0) and Ghostscript ignored +% \pdfterm{Metadata} but honored \pdfterm{PUT} so that's what versions +% of \pkgname{hyperxmp} prior to~1.3 used. As all current +% PostScript-to-\acro{PDF} generators seem to honor the +% \pdfterm{Metadata} |pdfmark|, \pkgname{hyperxmp} now uses that +% mechanism to point the document catalog to our metadata stream. % \begin{macrocode} \pdfmark{% - pdfmark=/PUT, + pdfmark=/Metadata, Raw={\string{Catalog\string}% << /Metadata \string{hyxmp@Metadata\string}% -- cgit v1.2.3