From 5ad4d6d7453a373f12f8e457bc3c3463c946b77f Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Tue, 5 Nov 2019 16:53:11 +0100 Subject: [PATCH] PDF/A-Erzeugung: die XMP-Metadaten selber erzeugen --- SL/DB/Helper/PDF_A.pm | 43 ++++++++++++--- SL/Template/LaTeX.pm | 39 ++++++++------ templates/pdf/pdf_a_metadata.xmp | 92 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 21 deletions(-) create mode 100644 templates/pdf/pdf_a_metadata.xmp diff --git a/SL/DB/Helper/PDF_A.pm b/SL/DB/Helper/PDF_A.pm index 4f5284435..f3388a336 100644 --- a/SL/DB/Helper/PDF_A.pm +++ b/SL/DB/Helper/PDF_A.pm @@ -5,6 +5,27 @@ use strict; use parent qw(Exporter); our @EXPORT = qw(create_pdf_a_print_options); +use Carp; +use Template; + +sub _create_xmp_data { + my ($self, %params) = @_; + + use Cwd; + my $template = Template->new({ + INTERPOLATE => 0, + EVAL_PERL => 0, + ABSOLUTE => 1, + PLUGIN_BASE => 'SL::Template::Plugin', + ENCODING => 'utf8', + }) || croak; + + my $output = ''; + $template->process(SL::System::Process::exe_dir() . '/templates/pdf/pdf_a_metadata.xmp', \%params, \$output) || croak $template->error; + + return $output; +} + sub create_pdf_a_print_options { my ($self) = @_; @@ -20,13 +41,23 @@ sub create_pdf_a_print_options { $::instance_conf->get_company }; + my $timestamp = DateTime->now_local->strftime('%Y-%m-%dT%H:%M:%S%z'); + $timestamp =~ s{(..)$}{:$1}; + return { - version => '3b', - meta_data => { - title => $self->displayable_name, - author => $author, - language => $pdf_language, - }, + version => '3b', + xmp => _create_xmp_data( + $self, + pdf_a_version => '3', + pdf_a_conformance => 'B', + producer => 'pdfTeX', + timestamp => $timestamp, # 2019-11-05T15:26:20+01:00 + meta_data => { + title => $self->displayable_name, + author => $author, + language => $pdf_language, + }, + ), }; } diff --git a/SL/Template/LaTeX.pm b/SL/Template/LaTeX.pm index 8b4c4e865..303fb7f37 100644 --- a/SL/Template/LaTeX.pm +++ b/SL/Template/LaTeX.pm @@ -420,7 +420,7 @@ sub _force_mandatory_packages { my ($self, @lines) = @_; my @new_lines; - my (%used_packages, $at_beginning_of_document); + my %used_packages; my @required_packages = qw(textcomp ulem); push @required_packages, 'embedfile' if $self->{pdf_a}; @@ -430,15 +430,27 @@ sub _force_mandatory_packages { } elsif (($line =~ m/\\documentclass/) && $self->{pdf_a}) { my $version = $self->{pdf_a}->{version} // '3a'; - my $meta = $self->{pdf_a}->{meta_data} // {}; + + if ($self->{pdf_a}->{xmp}) { + my $xmp_file_name = $self->{userspath} . "/pdfa.xmp"; + my $out = IO::File->new($xmp_file_name, ">:encoding(utf-8)") || croak "Error creating ${xmp_file_name}: $!"; + $out->print(Encode::encode('utf-8', $self->{pdf_a}->{xmp})); + $out->close; + + } else { + my $meta = $self->{pdf_a}->{meta_data} // {}; + + push @new_lines, ( + "\\RequirePackage{filecontents}\n", + "\\begin{filecontents*}{\\jobname.xmpdata}\n", + ($meta->{title} ? sprintf("\\Title{%s}\n", $meta->{title}) : ""), + ($meta->{author} ? sprintf("\\Author{%s}\n", $meta->{author}) : ""), + ($meta->{language} ? sprintf("\\Language{%s}\n", $meta->{language}) : ""), + "\\end{filecontents*}\n", + ); + } push @new_lines, ( - "\\RequirePackage{filecontents}\n", - "\\begin{filecontents*}{\\jobname.xmpdata}\n", - ($meta->{title} ? sprintf("\\Title{%s}\n", $meta->{title}) : ""), - ($meta->{author} ? sprintf("\\Author{%s}\n", $meta->{author}) : ""), - ($meta->{language} ? sprintf("\\Language{%s}\n", $meta->{language}) : ""), - "\\end{filecontents*}\n", $line, "\\usepackage[a-${version},mathxmp]{pdfx}[2018/12/22]\n", "\\usepackage[genericmode]{tagpdf}\n", @@ -449,17 +461,14 @@ sub _force_mandatory_packages { next; } elsif ($line =~ m/\\begin\{document\}/) { - $at_beginning_of_document = 1; push @new_lines, map { "\\usepackage{$_}\n" } grep { !$used_packages{$_} } @required_packages; + push @new_lines, $line; + push @new_lines, map { $self->_embed_file_directive($_) } @{ $self->{pdf_attachments} // [] }; + + next; } push @new_lines, $line; - - if ($at_beginning_of_document) { - $at_beginning_of_document = 0; - - push @new_lines, map { $self->_embed_file_directive($_) } @{ $self->{pdf_attachments} // [] }; - } } return @new_lines; diff --git a/templates/pdf/pdf_a_metadata.xmp b/templates/pdf/pdf_a_metadata.xmp new file mode 100644 index 000000000..a26157b2e --- /dev/null +++ b/templates/pdf/pdf_a_metadata.xmp @@ -0,0 +1,92 @@ + + + + + + + + + http://ns.adobe.com/pdfx/1.3/ + pdfx + PDF/X Schema + + + external + URL to an online version or preprint + AuthoritativeDomain + Text + + + + + http://www.aiim.org/pdfua/ns/id/ + pdfuaid + PDF/UA ID Schema + + + internal + Part of PDF/UA standard + part + Integer + + + + + PRISM metadata + http://prismstandard.org/namespaces/basic/2.2/ + prism + + + aggregationType + Text + external + The type of publication. If defined, must be one of book, catalog, feed, journal, magazine, manual, newsletter, pamphlet. + + + url + URL + external + URL for the article or unit of content + + + + + + + + [% producer | xml %] + + + application/pdf +[% IF meta_data.title %] + [% meta_data.title | xml %] +[% END %] + v3 +[% IF meta_data.language %] + [% meta_data.language | xml %] +[% END %] + + + + + + + [% pdf_a_version | xml %] + [% pdf_a_conformance | xml %] + + + [% producer | xml %] + [% timestamp | xml %] + [% timestamp | xml %] + [% timestamp | xml %] + + + + + + + -- 2.20.1