diff options
author | Norbert Preining <norbert@preining.info> | 2021-04-17 03:00:41 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-04-17 03:00:41 +0000 |
commit | 8ca7af6e140fdaee415715e4a537d8f1a9305198 (patch) | |
tree | 7ca5f98e34ec0c9e917f70c3577a3a3b0cff176f /support/latexmk/example_rcfiles | |
parent | 487e248ea8406af82362ed0cf749198b48b38183 (diff) |
CTAN sync 202104170300
Diffstat (limited to 'support/latexmk/example_rcfiles')
-rw-r--r-- | support/latexmk/example_rcfiles/chapterbib-latexmkrc | 21 | ||||
-rw-r--r-- | support/latexmk/example_rcfiles/hyperxmp-latexmkrc | 200 |
2 files changed, 211 insertions, 10 deletions
diff --git a/support/latexmk/example_rcfiles/chapterbib-latexmkrc b/support/latexmk/example_rcfiles/chapterbib-latexmkrc index 403cbd6ef5..e5c2cb6250 100644 --- a/support/latexmk/example_rcfiles/chapterbib-latexmkrc +++ b/support/latexmk/example_rcfiles/chapterbib-latexmkrc @@ -15,32 +15,33 @@ $bibtex = 'bibtex %O %S'; $bibtex_save = $bibtex; $bibtex = 'internal bibtex_fix %R %D %S'; -# MUST NOT use bibtex_fudge (i.e., change of directory before running bibtex). -# That's not needed in post-2019 versions of bibtex, and messes up -# things with chapterbib. So turn it off: -$bibtex_fudge = 0; - $clean_ext .= " %R-mod.blg %R-mod.aux %R-mod.bbl"; sub bibtex_fix { my ($root, $dest, $source) = @_; - local ($base_tex, $path, $ext) = fileparse( $source, '\.[^\.]*' ); + local ($base_bare, $path, $ext) = fileparse( $source, '\.[^\.]*' ); + if ($path eq './') { $path = ''; } + local $base = $path.$base_bare; my $ret = 0; - if ( $base_tex eq $root ) { + if ( $base_bare eq $root ) { print "--- Will run bibtex on modified '$root.aux' file\n"; - my $aux_mod_base = $path.$base_tex."-mod"; + my $aux_mod_base = $base."-mod"; local $out_fh = new FileHandle "> $aux_mod_base$ext"; if (!$out_fh) { die "Cannot write to '$aux_mod_base$ext'\n"; } local $level = 0; fix_aux( $source ); close $out_fh; - $ret = Run_subst( $bibtex_save, 2, undef, "$aux_mod_base.aux", undef, $aux_mod_base ); + # Override source, dest, and basenames, since they are to have the path given + # in the arguments to this subroutine, instead of the path given in the + # corresponding names in the rule. Latexmk may change directory before + # calling this subroutine, and adjusts the arguments accordingly: + $ret = Run_subst( $bibtex_save, 2, undef, "$aux_mod_base$ext", "$aux_mod_base.bbl", $aux_mod_base ); foreach ( 'bbl', 'blg' ) { copy "$aux_mod_base.$_", "$path$root.$_"; } } else { - $ret = Run_subst( $bibtex_save ); + $ret = Run_subst( $bibtex_save, 2, undef, $source, $dest, $base ); } return $ret; } diff --git a/support/latexmk/example_rcfiles/hyperxmp-latexmkrc b/support/latexmk/example_rcfiles/hyperxmp-latexmkrc new file mode 100644 index 0000000000..e0a80a7f40 --- /dev/null +++ b/support/latexmk/example_rcfiles/hyperxmp-latexmkrc @@ -0,0 +1,200 @@ +# Configuration of latexmk so that it works with the hyperxmp package. +# Hyperxmp puts document xmp metadata in the pdf file, and one of the +# fields in that metadata is byteCount, which is the size of the pdf file. +# This configuration ensures that the byteCount is present and correctly +# equals the pdf file's size. +# +# Method of operation: +# For any command that might produce a pdf file, prepend "internal mycmd3 " +# to the previously configured command, so that a subroutine mycmd3 is +# called. It runs the expected command and then does post-processing if +# the output file is a pdf file. + +foreach my $cmd ( "latex", "lualatex", "pdflatex", "xelatex", + "dvipdf", "xdvipdfmx", "ps2pdf" ) { + ${$cmd} = "internal mycmd ${$cmd}"; +} + +#====================================================== + +sub mycmd { + # Run command, and do extra processing of output file, if it is a pdf + # file. + # This subroutine is run in a rule context, so that $rule is the name of + # the rule and $$Pdest is the destination file name. + + # Identification string for messages: + local $name = "$My_name.mycmd"; + + my $retval = system @_; + + if ( $$Pdest =~ /\.pdf$/ ) { + fix_pdf( $$Pdest ); + } + return $retval; +} + +#====================================================== + +sub fix_pdf { + # Change/insert byteCount field with correct file length, while preserving + # the file size and the length of the stream containing xmp metadata. + # Return 1 on success, else 0. + + local $pdf_name = shift; + local $tmp_name = "$pdf_name.new.pdf"; + local $pdf_size = (stat($pdf_name))[7]; + warn "Inserting/correcting byteCount field in '$pdf_name' ...\n"; + + # Strings surrounding (and identifying) the byteCount field, and other + # parts of the xmp packet: + local $xmp_start = '<x:xmpmeta xmlns:x="adobe:ns:meta/">'; + local $decl_bC = '<pdfaProperty:name>byteCount</pdfaProperty:name>'; + local $pre_bC = '<prism:byteCount>'; + local $post_bC = '</prism:byteCount>'; + local $pC = '<prism:pageCount>'; + local $rd_end = '</rdf:Description>'; + local $xmp_end = '</x:xmpmeta>'; + + local *PDF; + local *TMP; + + if (! open PDF, "<", $pdf_name ) { + warn " Cannot read '$pdf_name'\n"; + return 0; + } + if ( ! open TMP, ">", $tmp_name ) { + warn " Cannot write temporary file '$tmp_name'\n"; + close PDF; + return 0; + } + local $status = 0; # 0 = no XMP packet, 1 = success, >= errors + while ( <PDF> ) { + # Only examine first XMP packet: + if ( ($status == 0) && /^\s*\Q$xmp_start\E/ ) { + local @xmp = $_; + local $len_padding = 0; + local $xmp_after_line = ''; + &xmp_get_mod; + print TMP @xmp; + # Insert correct padding to leave file size unchanged: + while ( $len_padding > 0 ) { + my $len_line = 64; + if ( $len_line > $len_padding ) { $len_line = $len_padding; } + $len_padding -= $len_line; + print TMP (' ' x ($len_line - 1) ), "\n"; + } + print TMP $xmp_after_line; + $xmp_after_line = ''; + } + else { + print TMP "$_"; + } + } + close PDF; + close TMP; + + if ($status == 0) { + warn " Could not insert/modify byteCount, since no XMP packet was found.\n"; + warn " So '$pdf_name' is unchanged,\n", + " and I will delete temporary file '$tmp_name'.\n"; + unlink $tmp_name; + } elsif ($status == 1) { + rename $tmp_name, $pdf_name + or die " Cannot move temporary file '$tmp_name' to '$pdf_name'.\n", + " Error is '$!'\n"; + } else { + warn " Could not insert correct byteCount. See above for reason.\n"; + warn " So '$pdf_name' is unchanged,\n", + " and I will delete temporary file '$tmp_name'.\n"; + unlink $tmp_name; + } + return ($status == 1); +} + +#====================================================== + +sub xmp_get_mod { + # Get xmp packet, given that @xmp contains its first line. + # Get amount of trailing padding, and line after that. + # If possible, insert a byteCount field: + # Either replace existing specification, if it exists, + # or insert one in expected place for hyperxmp, if the XMP packet + # matches what hyperxmp would produce. + # Return xmp packet in @xmp, amount of padding needed in $len_padding, + # line after that in $xmp_after_line, and error code in $error. + # Set $status appropriately: 1 for success; >=1 for failure. + + $len_padding = 0; + $xmp_after_line = ''; + + my $bC_index = -1; + my $xmp_end_found = 0; + my $decl_bC_found = 0; + while ( <PDF> ) { + push @xmp, $_; + if ( /^\s*\Q$xmp_end\E/ ) { + $xmp_end_found = 1; + # Get amount of padding; + while (<PDF>) { + if ( /^\s*$/ ) { + $len_padding += length($_); + } else { + $xmp_after_line = $_; + last; + } + } + last; + } + elsif ( $bC_index >= 0 ){ + next; + } + # Rest of conditions only apply if no place yet found for byteCount + # specification. + elsif ( /^(\s*)\Q$pre_bC\E.*?\Q$post_bC\E\s*$/ ) { + $bC_index = $#xmp; + } + elsif ( /^\s*\Q$decl_bC\E/ ) { + $decl_bC_found = 1; + } + elsif ( /^(\s*)\Q$rd_end\E/ ){ + # End of rdf:Description block. + # So having previous declaration of byteCount is irrelevant. + $decl_bC_found = 0; + } + elsif ( $decl_bC_found && /^(\s*)\Q$pC\E/ ){ + $bC_index = $#xmp; + pop @xmp; + push @xmp, '', $_; + } + + } # End reading of XMP + + if ($bC_index < 0) { + if ( ! $xmp_end_found ) { + warn " End of XMP packet not found.\n"; + $status = 2; + } + elsif ( ! $decl_bC_found ) { + warn " XMP packet not in appropriate hyperxmp-compatible format.\n"; + $status = 3; + } + return; + } + my $new_line = ' ' . $pre_bC . $pdf_size . $post_bC . "\n"; + my $old_line = $xmp[$bC_index]; + my $delta_len = length($new_line) - length($old_line); + if ($delta_len > $len_padding) { + warn " Cannot get padding correct for '$pdf_name'.\n", + " Length change of bC line = $delta_len; ", + " Padding bytes available = $len_padding.\n"; + $status = 4; + return; + } else { + $len_padding -= $delta_len; + $xmp[$bC_index] = $new_line; + $status = 1; + } +} + +#====================================================== |