summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/xmpincl/xmpincl.dtx
blob: 2b9b8744cd1edf7c8d377fc732e540efbf8b0200 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
% \iffalse meta-comment
%
% Copyright (C) 2004 by Maarten Sneep <sneep@nat.vu.nl>
% -----------------------------------------------------
% 
% This work is licensed under the CC-GNU GPL, the human readable license
% can be found here, with a link to the full text on this page.
% http://creativecommons.org/licenses/GPL/2.0/
%
% To process this file run the accompanying xmpincl.ins file through tex.
% To get the documentation, run this file through pdfLaTeX.
%
% \fi
%
% \iffalse
%
%<*driver>
\ProvidesFile{xmpincl.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{xmpincl}
%<*package>
    [2021/08/31 v2.3 Include XMP data in pdflatex]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{hyperref}
\usepackage{url}
\usepackage{xmpincl}
\hypersetup{colorlinks=true, pdftitle={Including XMP in pdflatex}, 
   pdfauthor={Maarten Sneep <sneep@nat.vu.nl>},
   pdfsubject={pdflatex and XMP inclusions.}, pdfkeywords={XMP, Creative Commons},
   pdfview={FitH}, pdfstartview={FitH}, pdfstartpage={1}, plainpages=false}
\includexmp{license}
\DisableCrossrefs
%\CodelineIndex
%\RecordChanges
%\OnlyDescription
\begin{document}
  \DocInput{xmpincl.dtx}
\end{document}
%</driver>
% \fi
%
% \CheckSum{121}
%
% \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}{2004/06/20}{Initial release}
% \changes{v1.1}{2004/06/20}{Fixed some miscelaneous typos and removed support 
%   for the package option}
% \changes{v1.2}{2004/12/12}{Correctly detect pdftex usage -- rely on the ifpdf 
%   package, not on whether the pdfoutput command is defined}
% \changes{v1.3}{2005/02/14}{Clarified which parts are included in the 
%   meta-information, and what isn't.}
% \changes{v2.0}{2005/02/15}{Major release. Added code that will append 
%   the xpacket bits, if they are not already there.}
% \changes{v2.1}{2005/03/24}{Minor update: ifpdf and Memoir no longer bite each 
%   other. When used with Memoir, version ``2005/03/23 v3.9 Patches for memoir 
%   class v1.61'' of mempatch.sty is required.}
% \changes{v2.2}{2008/05/10}{Minor update: made |~| and |&| normal characters 
%   when writing the xmpi file. I still need to find a way to include |%| 
%   characters in the xmpi file.}
% \changes{v2.3}{2021/08/31}{Replaced \cs{if}\cs{par} with \cs{ifx}\cs{par}
%   because the former caused an error with the new definition of \cs{par}.}
%
% \GetFileInfo{xmpincl.dtx}
%
% \DoNotIndex{\newcommand,\newenvironment}
% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
% \DoNotIndex{\@ne}
% \DoNotIndex{\advance,\begingroup,\catcode,\closein}
% \DoNotIndex{\closeout,\day,\def,\edef,\else,\empty,\endgroup}
%
% \title{The \textsf{XMP} inclusion package\thanks{This document
%   corresponds to \textsf{xmpincl.dtx}~\fileversion, dated \filedate.}}
% \author{Maarten Sneep \\ \href{mailto:sneep@nat.vu.nl}{sneep@nat.vu.nl}}
% \date{\filedate}
%
% \maketitle
%
% \section{Introduction}
%
% The |XMP| (eXtensible Metadata Platform) is a framework to add metadata
% to digital material to enhance the workflow in publication. References
% are given below, but the essence is that the metadata is stored in an
% |XML| file, and this XML stream is then embedded in the file to which it
% applies. How you create this |XML| file is up to you, but I started
% investigating this, because I wanted to embed some licensing information
% in the files I create. The license I chose is one of the
% \textsf{Creative Commons} licenses, and their web-site offers this
% information in a valid |XML| file, suitable for direct inclusion.
%
% Note that this package is released under the
% \href{http://creativecommons.org/licenses/GPL/2.0/}{CC-GNU GPL} license.
% You can redistribute, but I kindly request that you update the version
% number, add a description of what you added or changed -- if possible
% with an explanation as to why -- and re-submit to CTAN, to keep it all
% in a single location. You can also submit changes to me, I regularly
% read |comp.text.tex| on usenet.
%
% Many thanks to James Howison for pushing me to put in the 
% |<?xpacket ?>| writing code, and suggesting to test whether they 
% are already there.
%
% Thanks to Martin Szummer for reporting that a |~| in an URL inside the 
% xmp file will not work.
%
% \subsection{Usage}
% 
% This package defines a single command, |\includexmp{}|. The |xmp| file
% is specified as an argument to this command. Although there is no real
% specification as to where the xml-stream should be inserted into the
% document, I would advise to put it at the start of the file, so call the
% |\includexmp{}| command before |\begin{document}|. Note that the package
% will add the extension |.xmp| to the base filename. To include the file
% |metadata.xmp|, use the following:
% 
%\begin{verbatim}
%. . .
%\usepackage{xmpincl}
%\includexmp{metadata}
%. . .
%\begin{document}
%. . .
%\end{verbatim}
%
% The file |metadata.xmp| should exist in the same directory as the master
% document. At the end of this documentation a sample file is included
% that will yield a valid |XMP| enhanced pdf file.
%
% Previous versions of this package required the inclusion of the
% |<?xpacket ?>| tags into the |XMP| file. This is against the standards,
% and several users requested that this functionality be added to the
% package. This new release (version 2.0) does add the |<?xpacket ?>|
% tags, if they are \emph{not} present in the |xmp| file.
%
% \subsection{New in the current release (\fileversion)}
% 
% There used to be a clash between the Memoir document class and the |ifpdf| package.
% As of version 2005/03/23 v3.9 of |mempatch.sty|, this clash has been removed, and 
% glue code that was present here, has been removed in this update. Note that this 
% may mean that you'll need to update your distribution to include teh latest 
% |mempatch.sty|.
%
% \subsection{References}
%
% \begin{itemize}
% \item \url{http://creativecommons.org/}
% \item \url{http://creativecommons.org/technology/xmp-help}
% \item \url{http://www.adobe.com/products/xmp}
% \end{itemize}
%
% \PrintChanges
% 
% \StopEventually{}
% 
% \section{Implementation}
%
% First we determine if we run under pdf\LaTeX{}, in pdf-production mode.
% This is best done with the |ifpdf| package. The Memoir documentclass also
% defines the |\ifpdf| boolean, but didn't actually load the |ifpdf| package.
% As of version ``2005/03/23 v3.9 Patches for memoir class v1.61'' of |mempatch.sty|
% teh loading of the ifpdf package is properly faked, and we no longer need to 
% check for the existence of the |\ifpdf| boolean. 
%    \begin{macrocode}
%<*package>
\RequirePackage{ifpdf}
\ifpdf\else
%    \end{macrocode}
% Apparently we do not run under pdflatex, or we are producing DVI.
% Someone else may try to do this correcltly for PostScript output. Note
% that a metacomment has to be added to the start of the |.ps| document,
% and that is something for which I have no clue on how to accomplish that
% from within \TeX{}.
%
% Right now I just skip non-pdflatex support and issue a warning. 
%    \begin{macrocode}
\PackageWarningNoLine{xmpincl}%
  {Only pdflatex is supported by the xmpincl package}
%    \end{macrocode}
% \DescribeMacro{includexmp}
% This is the latex (|DVI|) edition: just issue a warning, and stop
% reading the rest of this file
%    \begin{macrocode}
\newcommand{\includexmp}[1]{%
  \PackageError{xmpincl}%
  {latex is not supported by the \protect\includexmp\space package}%
  {You tried to include XMP metadata in DVI production.\MessageBreak
   That doesn't work, and I friendly tried to warn you.\MessageBreak
   Just continue and pretend nothing is wrong,\MessageBreak
   but please remove the package or switch to pdflatex.}
}
%    \end{macrocode}
% Stop reading this file, as the rest only works when generating |pdf|
% directly.
%    \begin{macrocode}
\relax\expandafter\endinput
\fi
%    \end{macrocode}
% The |ifthen| package is loaded, for the string comparisons later on.
%    \begin{macrocode}
\RequirePackage{ifthen}
%    \end{macrocode}
% \DescribeMacro{mcs@xmpincl@patchFile}
% Based on popular feedback, we now add the |<?xpacket . . .?>| parts
% ourselves. This can be a bit tricky, so bear with me. I basically create
% a new file |.xmpi| which starts off with the |<?xpacket ?>| tag, copy
% the whole |XMP| file to this new file, and add the |<?xpacket ?>| close
% tag. Of course, this is new functionality, so we still have to take care
% of our backward compatibility issues. So we check that what we've read is 
% not an |<?xpacket ?>| tag. I'm aware of the odd combination of \TeX{}
% and \LaTeX{} coding here, but I didn't manage to get the string 
% comparison working in palin \TeX{} code, and this \LaTeX{} code is
% maintained by others, something I really don't mind.
%
% The macro starts off by opening a few files, one for reading the user 
% supplied |XMP|, and another one for writing it back out again, but this 
% time with the |<?xpacket ?>| bits included.
%    \begin{macrocode}
\newcommand*{\mcs@xmpincl@patchFile}[1]{
\begingroup
\newwrite\xmpinclWrite
\newread\xmpinclRead
\immediate\openin\xmpinclRead #1.xmp
\immediate\openout\xmpinclWrite #1.xmpi
%    \end{macrocode}
% \DescribeMacro{mcs@xmpinclStart}
% \DescribeMacro{mcs@xmpinclStartAlt}
% \DescribeMacro{mcs@xmpinclEnd}
% The begin and en |<?xpacket ?>| strings are put in some macros to
% easier access. Yes, that start string was double checked against the
% documentation provided by Adobe. The alternate starting string is there
% because the |id| seems to be optional, if I understand the documentation
% correctly.
%    \begin{macrocode}
\newcommand{\mcs@xmpinclStart}%
  {<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> }
\newcommand{\mcs@xmpinclStartAlt}%
  {<?xpacket begin='' id=''?> }
\newcommand{\mcs@xmpinclEnd}%
  {<?xpacket end='r'?> }
%    \end{macrocode}
% Next we change the catcode of |#| to `other'. This is just to prevent
% misinterpretation of this character. Of course there are more special
% characters, but as far as I can see, these aren't treated in any special
% way (|#| is doubled by \TeX{} to |##|).
%    \begin{macrocode}
\catcode`\#=12
%    \end{macrocode}
% We deactivate |~| and |&| as well. 
%    \begin{macrocode}
\catcode`\~=12
\catcode`\&=12
%    \end{macrocode}
% Read the first line of the input file, and compare it to the start tag,
% and the alternate start tag. If they match, write out the standard start
% tag (including the |id|). If they don't match, write out the start tag,
% followed by the line we've just read.
%    \begin{macrocode}
\immediate\read\xmpinclRead to\xmpinclReadln%
\ifthenelse{%
  \equal{\mcs@xmpinclStart}{\xmpinclReadln}%
  \or%
  \equal{\mcs@xmpinclStartAlt}{\xmpinclReadln}%
}%
{%
  \immediate\write\xmpinclWrite{\mcs@xmpinclStart}%
}%
{%
  \immediate\write\xmpinclWrite{\mcs@xmpinclStart}%
  \immediate\write\xmpinclWrite{\xmpinclReadln}%
}%
%    \end{macrocode}
% Start the |\loop|, and read a line. Check if it is equal to the end tag
% or to |\par|, and if it isn't, write it out to the |.xmpi| file. The
% check against |\par| ensures that empty lines are skipped, and not
% replaced by |\par|.
% 
% The |\ifeof| test checks whether we've reached the end of the original
% |.xmp| file, and |\repeat|s the |\loop| if we haven't.
%    \begin{macrocode}
\loop%
  \immediate\read\xmpinclRead to\xmpinclReadln%
  \ifthenelse{%
    \equal{\mcs@xmpinclEnd}{\xmpinclReadln}%
    }{% Note: no if.
    }{%
    \ifx\par\xmpinclReadln\else%
      \immediate\write\xmpinclWrite{\xmpinclReadln}%
    \fi%
  }%
  \ifeof\xmpinclRead\else%
\repeat
%    \end{macrocode}
% Since we skipped any end |<?xpacket ?>| tags, we write it here. After
% that we close both files and end the current group (restoring the
% meaning of |#|, |&|, and |~|).
%    \begin{macrocode}
\immediate\write\xmpinclWrite{\mcs@xmpinclEnd}
\immediate\closein\xmpinclRead
\immediate\closeout\xmpinclWrite
\endgroup
}
%    \end{macrocode}
% \DescribeMacro{includexmp}
% The meat of the business. Actually pretty trivial, once you know
% how\ldots
%    \begin{macrocode}
\newcommand{\includexmp}[1]{%
%    \end{macrocode}
% First check that the file can be found, and if we use the new methods,
% convert it.
%    \begin{macrocode}
  \IfFileExists{#1.xmp}{
    \mcs@xmpincl@patchFile{#1}
%    \end{macrocode}
% Reset the |\pdfcompresslevel| to 0, do not compress the |XML| data.
% This is recommended by Adobe, so that file utilities can grep the |.pdf|
% file for metadata, without the full capability to actually parse the
% |pdf| file.
% Keep the change local.
%    \begin{macrocode}
    \begingroup
      \pdfcompresslevel=0
%    \end{macrocode}
% Write out the |pdf| object, with the specifications given in the
% reference manual found at \url{http://www.adobe.com/products/xmp}. The
% |file| attribute reads the specified file from disk, although it is not
% clear to me if it uses the full \TeX{} search path. To be safe, specify
% a local path relative to the master document. Depending on the
% compatibility level, we use the original file, or the newly generated
% version.
%    \begin{macrocode}
      \immediate\pdfobj stream attr {/Type /Metadata /Subtype /XML}
      file{#1.xmpi}
%    \end{macrocode}
% Also add the newly created object to the catalog.
%    \begin{macrocode}
      \pdfcatalog{/Metadata \the\pdflastobj\space 0 R}
%    \end{macrocode}
% end the group, which resets the compression to whatever it was before.
%    \begin{macrocode}
    \endgroup
  }
%    \end{macrocode}
% The file does not exist, and we have to generate an error. Declare a
% placeholder for the missing file-name, to prevent double execution of
% the macro.
%    \begin{macrocode}
  {\newcommand{\mcs@xmpincl@filename}{#1.xmp}
    \PackageError{xmpincl}%
    {The file \mcs@xmpincl@filename\space was not found}
    {The file \mcs@xmpincl@filename\space The metadata file 
     wasn't found.\MessageBreak Oops.}
  }
}
%</package>
%    \end{macrocode}
% 
% \section{A sample \texttt{.xmp} file}
% Note that this is the license of this package, 
% \href{http://creativecommons.org/licenses/GPL/2.0/}{CC-GNU GPL}.
% 
%    \begin{macrocode}
%<*license>
<x:xmpmeta xmlns:x='adobe:ns:meta/'>
   <rdf:RDF xmlns="http://web.resource.org/cc/"
      xmlns:dc="http://purl.org/dc/elements/1.1/"
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <Work rdf:about="">
         <dc:title>xmpincl</dc:title>
         <dc:date>2005</dc:date>
         <dc:description>
            A LaTeX package to include XMP metadata in 
            files generated through pdfLaTeX
         </dc:description>
         <dc:creator>
            <Agent><dc:title>Maarten Sneep</dc:title></Agent>
         </dc:creator>
         <dc:rights>
            <Agent><dc:title>Maarten Sneep</dc:title></Agent>
         </dc:rights>
         <dc:source
            rdf:resource="ftp://ftp.tex.ac.uk/tex&#45;archive/macros/latex/contrib/xmpincl.tar.gz"/>
         <license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
      </Work>
      <License rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
         <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
         <permits rdf:resource="http://web.resource.org/cc/Distribution" />
         <requires rdf:resource="http://web.resource.org/cc/Notice" />
         <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
         <requires rdf:resource="http://web.resource.org/cc/ShareAlike" />
         <requires rdf:resource="http://web.resource.org/cc/SourceCode" />
      </License>
   </rdf:RDF>
</x:xmpmeta>
%</license>
%    \end{macrocode}
% \Finale
\endinput