summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-01-23 21:58:36 +0000
committerKarl Berry <karl@freefriends.org>2020-01-23 21:58:36 +0000
commit4986533634ee4841ae45b9cf3134f045f1c4a891 (patch)
tree67f9cca1139594569703d71df9135547418cc480 /Master/texmf-dist
parent782e708839f16d9363399aca8f1476b9094b879a (diff)
pdfbook2 (23jan20)
git-svn-id: svn://tug.org/texlive/trunk@53521 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/doc/man/man1/pdfbook2.1121
-rw-r--r--Master/texmf-dist/doc/man/man1/pdfbook2.man1.pdfbin0 -> 22546 bytes
-rw-r--r--Master/texmf-dist/doc/support/pdfbook2/README12
-rwxr-xr-xMaster/texmf-dist/scripts/pdfbook2/pdfbook2380
4 files changed, 362 insertions, 151 deletions
diff --git a/Master/texmf-dist/doc/man/man1/pdfbook2.1 b/Master/texmf-dist/doc/man/man1/pdfbook2.1
new file mode 100644
index 00000000000..c761447b536
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/pdfbook2.1
@@ -0,0 +1,121 @@
+.TH pdfbook2 1 "January 22, 2020" "" "pdfbook2 - transform pdf files to booklets"
+
+.SH NAME
+pdfbook2 \- transform pdf files into booklets for double-sided printing
+
+.SH SYNOPSIS
+\fBpdfbook2\fR [ \fIoptions\fR ] \fIINPUT\fR [ \fIINPUT\fR, ...]
+
+.SH DESCRIPTION
+Create print-ready PDF files from some \fIINPUT\fR PDF files for booklet printing. The resulting files need to be printed in landscape/long edge double sided printing. The default paper format depends on the locale and is choosen by pdfjam. It can be set with the --paper option.
+.PP
+Before the pdf is composed the \fIINPUT\fR file is cropped to the relevant area in order to discard unnecessary white spaces. In this process, all pages are cropped to the same dimensions. Extra margins can be defined at the edges of the booklet and in the middle where the binding occurs.
+.PP
+The \fIOUTPUT\fR is written to \fIINPUT\fR-book.pdf. Existing files will be overwritten. All input files are processed seperatly.
+
+.SH EXAMPLE
+To simply \fBcreate a booklet\fR from input.pdf you can use
+.PP
+.nf
+.RS
+pdfbook2 input.pdf
+.RE
+.fi
+.PP
+to create input-book.pdf. To select a special \fBtype of paper\fR you can do
+.PP
+.nf
+.RS
+pdfbook2 --paper=letter input.pdf
+.RE
+.fi
+.PP
+for letter or
+.PP
+.nf
+.RS
+pdfbook2 --paper=a4paper input.pdf
+.RE
+.fi
+.PP
+for standard A4. To increase the \fBinner margin for binding\fR use
+.PP
+.nf
+.RS
+pdfbook2 --inner-margin=200 input.pdf
+.RE
+.fi
+.PP
+to increase the default value of 150. You can submit \fBmultiple files\fR to the
+script for processing like
+.PP
+.nf
+.RS
+pdfbook2 input1.pdf input2.pdf
+.RE
+.fi
+.PP
+which will result in input1-book.pdf and input2-book.pdf.
+
+.SH OPTIONS
+.TP
+.BR \-\-version
+show program's version number and exit
+.TP
+.BR -h ", " --help
+show help message and exit
+
+.SS GENERAL
+.TP
+.BR -p ", " --paper = \fISTR\fR
+Format of the output paper dimensions as latex keyword (e.g. a4paper, letterpaper, legalpaper, ...)
+.TP
+.BR -s ", " --short-edge
+Format the booklet for short-edge double-sided printing
+.TP
+.BR -n ", " --no-crop
+Prevent the cropping to the content area
+
+.SS MARGINS
+.TP
+.BR -o ", " --outer-margin = \fIINT\fR
+Defines the outer margin in the booklet (default: 40)
+.TP
+.BR -i ", " --inner-margin = \fIINT\fR
+Defines the inner margin between the pages in the booklet (default: 150)
+.TP
+.BR -t ", " --top-margin = \fIINT\fR
+Defines the top margin in the booklet (default: 30)
+.TP
+.BR -b ", " --bottom-margin = \fIINT\fR
+Defines the bottom margin in the booklet (default: 30)
+
+.SS ADVANCED
+.TP
+.BR --signature = \fIINT\fR
+Define the signature for the booklet handed to pdfjam, needs to be multiple of 4 (default: 4)
+.TP
+.BR --signature* = \fIINT\fR
+Same as --signature
+.TP
+.BR --resolution = \fIINT\fR
+Resolution used by ghostscript in bp (default: 72)
+
+.SH "SEE ALSO"
+.BR pdfbook (1),
+.BR pdfjam (1),
+.BR pdfcrop (1)
+
+.SH ABOUT
+pdfbook2 v1.4 (https://github.com/jenom/pdfbook2)
+.br
+(c) 2015 - 2020 Johannes Neumann (http://www.neumannjo.de)
+.br
+licensed under GPLv3 (http://www.gnu.org/licenses/gpl-3.0)
+.br
+based on pdfbook by David Firth with help from Marco Pessotto
+
+.SH LICENSE
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/Master/texmf-dist/doc/man/man1/pdfbook2.man1.pdf b/Master/texmf-dist/doc/man/man1/pdfbook2.man1.pdf
new file mode 100644
index 00000000000..c7390800298
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/pdfbook2.man1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/support/pdfbook2/README b/Master/texmf-dist/doc/support/pdfbook2/README
index 2b72d40f066..e27738188bc 100644
--- a/Master/texmf-dist/doc/support/pdfbook2/README
+++ b/Master/texmf-dist/doc/support/pdfbook2/README
@@ -1,8 +1,8 @@
pdfbook2 - transform pdf files to booklets
==========================================
- pdfbook2 v1.3 (https://github.com/jenom/pdfbook2)
- (c) 2015 - 2019 Johannes Neumann (http://www.neumannjo.de)
+ pdfbook2 v1.4 (https://github.com/jenom/pdfbook2)
+ (c) 2015 - 2020 Johannes Neumann (http://www.neumannjo.de)
licensed under GPLv3 (http://www.gnu.org/licenses/gpl-3.0)
based on pdfbook by David Firth with help from Marco Pessotto
@@ -45,7 +45,7 @@ INSTALLATION
REQUIREMENTS
- python 2.7, pdfjam, pdfcrop and their dependencies.
+ python 3.6, pdfjam, pdfcrop and their dependencies.
EXAMPLES
@@ -115,6 +115,12 @@ OPTIONS
CHANGELOG
+ 1.4 2020/01/20
+
+ - migration to Python 3
+ - fixed bug if the input document had only one page
+ - fix for signature option not working
+
1.3 2019/08/12
- removed wait after popen to prevent deadlock with very large documents
diff --git a/Master/texmf-dist/scripts/pdfbook2/pdfbook2 b/Master/texmf-dist/scripts/pdfbook2/pdfbook2
index c5bc8677db2..f9bb012cc75 100755
--- a/Master/texmf-dist/scripts/pdfbook2/pdfbook2
+++ b/Master/texmf-dist/scripts/pdfbook2/pdfbook2
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
""" pdfbook2 - transform pdf files to booklets
This program is free software: you can redistribute it and/or modify
@@ -16,219 +16,303 @@
"""
-import sys
-import subprocess
import os
-from optparse import OptionParser, OptionGroup, HelpFormatter
import shutil
+import subprocess
+import sys
+from optparse import HelpFormatter, OptionGroup, OptionParser
-
-#===============================================================================
+# ===============================================================================
# Create booklet for file $name
-#===============================================================================
+# ===============================================================================
-def booklify( name, opts ):
- #------------------------------------------------------ Check if file exists
- print "\nProcessing", name
- if not os.path.isfile( name ):
- print "SKIP: file not found."
+
+def booklify(name, opts):
+ # ------------------------------------------------------ Check if file exists
+ print("\nProcessing", name)
+ if not os.path.isfile(name):
+ print("SKIP: file not found.")
return
- print "Getting bounds...",
+ print("Getting bounds...", end=" ")
sys.stdout.flush()
- #---------------------------------------------------------- useful constants
- bboxName = "%%HiResBoundingBox:"
+ # ---------------------------------------------------------- useful constants
+ bboxName = b"%%HiResBoundingBox:"
tmpFile = ".crop-tmp.pdf"
- #------------------------------------------------- find min/max bounding box
+ # ------------------------------------------------- find min/max bounding box
if opts.crop:
- p = subprocess.Popen( ["pdfcrop", "--verbose",
- "--resolution", repr( opts.resolution ),
- name, tmpFile],
- stdout = subprocess.PIPE,
- stderr = subprocess.PIPE )
+ p = subprocess.Popen(
+ ["pdfcrop", "--verbose", "--resolution", repr(opts.resolution), name, tmpFile],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
out, err = p.communicate()
- if len( err ) != 0:
- print err
- print "\n\nABORT: Problem getting bounds"
- sys.exit( 1 )
+ if len(err) != 0:
+ print(err)
+ print("\n\nABORT: Problem getting bounds")
+ sys.exit(1)
lines = out.splitlines()
- bboxes = [s[len( bboxName ) + 1:] for s in lines if s.startswith( bboxName )]
- bounds = [[float( x ) for x in bbox.split()] for bbox in bboxes ]
- minLOdd = min( [bound[0] for bound in bounds[::2] ] )
- maxROdd = max( [bound[2] for bound in bounds[::2] ] )
- minLEven = min( [bound[0] for bound in bounds[1::2] ] )
- maxREven = max( [bound[2] for bound in bounds[1::2] ] )
- minT = min( [bound[1] for bound in bounds ] )
- maxB = max( [bound[3] for bound in bounds ] )
+ bboxes = [s[len(bboxName) + 1 :] for s in lines if s.startswith(bboxName)]
+ bounds = [[float(x) for x in bbox.split()] for bbox in bboxes]
+ minLOdd = min([bound[0] for bound in bounds[::2]])
+ maxROdd = max([bound[2] for bound in bounds[::2]])
+ if len(bboxes) > 1:
+ minLEven = min([bound[0] for bound in bounds[1::2]])
+ maxREven = max([bound[2] for bound in bounds[1::2]])
+ else:
+ minLEven = minLOdd
+ maxREven = maxROdd
+ minT = min([bound[1] for bound in bounds])
+ maxB = max([bound[3] for bound in bounds])
widthOdd = maxROdd - minLOdd
widthEven = maxREven - minLEven
- maxWidth = max( widthOdd, widthEven )
+ maxWidth = max(widthOdd, widthEven)
minLOdd -= maxWidth - widthOdd
maxREven += maxWidth - widthEven
- print "done"
+ print("done")
sys.stdout.flush()
- #--------------------------------------------- crop file to area of interest
- print "cropping...",
+ # --------------------------------------------- crop file to area of interest
+ print("cropping...", end=" ")
sys.stdout.flush()
- p = subprocess.Popen( ["pdfcrop",
- "--bbox-odd", "{L} {T} {R} {B}".format( L = minLOdd - opts.innerMargin / 2,
- T = minT - opts.topMargin,
- R = maxROdd + opts.outerMargin,
- B = maxB + opts.outerMargin ),
- "--bbox-even", "{L} {T} {R} {B}".format( L = minLEven - opts.outerMargin,
- T = minT - opts.topMargin,
- R = maxREven + opts.innerMargin / 2,
- B = maxB + opts.outerMargin ),
- "--resolution", repr( opts.resolution ),
- name,
- tmpFile],
- stdout = subprocess.PIPE,
- stderr = subprocess.PIPE )
+ p = subprocess.Popen(
+ [
+ "pdfcrop",
+ "--bbox-odd",
+ "{L} {T} {R} {B}".format(
+ L=minLOdd - opts.innerMargin / 2,
+ T=minT - opts.topMargin,
+ R=maxROdd + opts.outerMargin,
+ B=maxB + opts.outerMargin,
+ ),
+ "--bbox-even",
+ "{L} {T} {R} {B}".format(
+ L=minLEven - opts.outerMargin,
+ T=minT - opts.topMargin,
+ R=maxREven + opts.innerMargin / 2,
+ B=maxB + opts.outerMargin,
+ ),
+ "--resolution",
+ repr(opts.resolution),
+ name,
+ tmpFile,
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
out, err = p.communicate()
- if len( err ) != 0:
- print err
- print "\n\nABORT: Problem with cropping"
- sys.exit( 1 )
- print "done"
+ if len(err) != 0:
+ print(err)
+ print("\n\nABORT: Problem with cropping")
+ sys.exit(1)
+ print("done")
sys.stdout.flush()
else:
- shutil.copy( name, tmpFile )
+ shutil.copy(name, tmpFile)
- #-------------------------------------------------------- create the booklet
- print "create booklet...",
+ # -------------------------------------------------------- create the booklet
+ print("create booklet...", end=" ")
sys.stdout.flush()
- pdfJamCallList = [ "pdfjam",
- "--booklet", "true",
- "--landscape",
- "--suffix", "book",
- "--signature", repr( opts.signature ),
- tmpFile ]
+ pdfJamCallList = [
+ "pdfjam",
+ "--landscape",
+ "--suffix",
+ "book",
+ tmpFile,
+ ]
+
+ # add option signature if it is defined else booklet
+ if opts.signature != 0:
+ pdfJamCallList.append("--signature")
+ pdfJamCallList.append(repr(opts.signature))
+ else:
+ pdfJamCallList.append("--booklet")
+ pdfJamCallList.append("true")
# add option --paper to call
if opts.paper is not None:
- pdfJamCallList.append( "--paper" )
- pdfJamCallList.append( opts.paper )
+ pdfJamCallList.append("--paper")
+ pdfJamCallList.append(opts.paper)
# add option --short-edge to call
if opts.shortedge:
# check if everyshi.sty exists as texlive recommends
- p = subprocess.Popen( ["kpsewhich", "everyshi.sty"],
- stdout = subprocess.PIPE,
- stderr = subprocess.PIPE )
+ p = subprocess.Popen(
+ ["kpsewhich", "everyshi.sty"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
out, err = p.communicate()
- if len( out ) == 0:
- print "\n\nABORT: The everyshi.sty latex package is needed for short-edge."
- sys.exit( 1 )
+ if len(out) == 0:
+ print("\n\nABORT: The everyshi.sty latex package is needed for short-edge.")
+ sys.exit(1)
else:
- pdfJamCallList.append( "--preamble" )
- pdfJamCallList.append( r"\usepackage{everyshi}\makeatletter\EveryShipout{\ifodd\c@page\pdfpageattr{/Rotate 180}\fi}\makeatother" )
+ pdfJamCallList.append("--preamble")
+ pdfJamCallList.append(
+ r"\usepackage{everyshi}\makeatletter\EveryShipout{\ifodd\c@page\pdfpageattr{/Rotate 180}\fi}\makeatother"
+ )
# run call to pdfJam to make booklet
- p = subprocess.Popen( pdfJamCallList,
- stdout = subprocess.PIPE,
- stderr = subprocess.PIPE )
+ p = subprocess.Popen(pdfJamCallList, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
- #-------------------------------------------- move file and remove temp file
- os.rename( tmpFile[:-4] + "-book.pdf", name[:-4] + "-book.pdf" )
- os.remove( tmpFile )
- print "done"
+ # -------------------------------------------- move file and remove temp file
+ os.rename(tmpFile[:-4] + "-book.pdf", name[:-4] + "-book.pdf")
+ os.remove(tmpFile)
+ print("done")
sys.stdout.flush()
-#===============================================================================
+# ===============================================================================
# Help formatter
-#===============================================================================
+# ===============================================================================
+
-class MyHelpFormatter ( HelpFormatter ):
+class MyHelpFormatter(HelpFormatter):
"""Format help with indented section bodies.
"""
- def __init__( self,
- indent_increment = 4,
- max_help_position = 16,
- width = None,
- short_first = 0 ):
- HelpFormatter.__init__(
- self, indent_increment, max_help_position, width, short_first )
+ def __init__(self, indent_increment=4, max_help_position=16, width=None, short_first=0):
+ HelpFormatter.__init__(self, indent_increment, max_help_position, width, short_first)
- def format_usage( self, usage ):
- return ( "USAGE\n\n%*s%s\n" ) % ( self.indent_increment, "", usage )
+ def format_usage(self, usage):
+ return ("USAGE\n\n%*s%s\n") % (self.indent_increment, "", usage)
- def format_heading( self, heading ):
- return "%*s%s\n\n" % ( self.current_indent, "", heading.upper() )
+ def format_heading(self, heading):
+ return "%*s%s\n\n" % (self.current_indent, "", heading.upper())
-#===============================================================================
+# ===============================================================================
# main programm
-#===============================================================================
+# ===============================================================================
if __name__ == "__main__":
- #------------------------------------------------------------ useful strings
+ # ------------------------------------------------------------ useful strings
usageString = "Usage: %prog [options] file1 [file2 ...]"
versionString = """
- %prog v1.3 (https://github.com/jenom/pdfbook2)
- (c) 2015 Johannes Neumann (http://www.neumannjo.de)
+ %prog v1.4 (https://github.com/jenom/pdfbook2)
+ (c) 2015 - 2020 Johannes Neumann (http://www.neumannjo.de)
licensed under GPLv3 (http://www.gnu.org/licenses/gpl-3.0)
based on pdfbook by David Firth with help from Marco Pessotto\n"""
defaultString = " (default: %default)"
- #------------------------------------------------- create commandline parser
- parser = OptionParser( usage = usageString, version = versionString,
- formatter = MyHelpFormatter( indent_increment = 4 ) )
-
- generalGroup = OptionGroup( parser, "General" )
- generalGroup.add_option( "-p", "--paper", dest = "paper", type = "str", action = "store",
- metavar = "STR",
- help = "Format of the output paper dimensions as latex keyword (e.g. a4paper, letterpaper, legalpaper, ...)" )
- generalGroup.add_option( "-s", "--short-edge", dest = "shortedge", action = "store_true",
- help = "Format the booklet for short-edge double-sided printing",
- default = False )
- generalGroup.add_option( "-n", "--no-crop", dest = "crop", action = "store_false",
- help = "Prevent the cropping to the content area",
- default = True )
- parser.add_option_group( generalGroup )
-
- marginGroup = OptionGroup( parser, "Margins" )
- marginGroup.add_option( "-o", "--outer-margin", type = "int", default = 40,
- dest = "outerMargin", action = "store", metavar = "INT",
- help = "Defines the outer margin in the booklet" + defaultString )
- marginGroup.add_option( "-i", "--inner-margin", type = "int", default = 150,
- dest = "innerMargin", action = "store", metavar = "INT",
- help = "Defines the inner margin between the pages in the booklet" + defaultString )
- marginGroup.add_option( "-t", "--top-margin", type = "int", default = 30,
- dest = "topMargin", action = "store", metavar = "INT",
- help = "Defines the top margin in the booklet" + defaultString )
- marginGroup.add_option( "-b", "--bottom-margin", type = "int", default = 30, metavar = "INT",
- dest = "bottomMargin", action = "store",
- help = "Defines the bottom margin in the booklet" + defaultString )
- parser.add_option_group( marginGroup )
-
- advancedGroup = OptionGroup( parser, "Advanced" )
- advancedGroup.add_option( "--signature", dest = "signature", action = "store", type = "int",
- help = "Define the signature for the booklet handed to pdfjam, needs to be multiple of 4" + defaultString,
- default = 4, metavar = "INT" )
- advancedGroup.add_option( "--signature*", dest = "signature", action = "store", type = "int",
- help = "Same as --signature", metavar = "INT" )
- advancedGroup.add_option( "--resolution", dest = "resolution", action = "store", type = "int",
- help = "Resolution used by ghostscript in bp" + defaultString,
- metavar = "INT", default = 72 )
- parser.add_option_group( advancedGroup )
+ # ------------------------------------------------- create commandline parser
+ parser = OptionParser(
+ usage=usageString, version=versionString, formatter=MyHelpFormatter(indent_increment=4)
+ )
+
+ generalGroup = OptionGroup(parser, "General")
+ generalGroup.add_option(
+ "-p",
+ "--paper",
+ dest="paper",
+ type="str",
+ action="store",
+ metavar="STR",
+ help="Format of the output paper dimensions as latex keyword (e.g. a4paper, letterpaper, legalpaper, ...)",
+ )
+ generalGroup.add_option(
+ "-s",
+ "--short-edge",
+ dest="shortedge",
+ action="store_true",
+ help="Format the booklet for short-edge double-sided printing",
+ default=False,
+ )
+ generalGroup.add_option(
+ "-n",
+ "--no-crop",
+ dest="crop",
+ action="store_false",
+ help="Prevent the cropping to the content area",
+ default=True,
+ )
+ parser.add_option_group(generalGroup)
+
+ marginGroup = OptionGroup(parser, "Margins")
+ marginGroup.add_option(
+ "-o",
+ "--outer-margin",
+ type="int",
+ default=40,
+ dest="outerMargin",
+ action="store",
+ metavar="INT",
+ help="Defines the outer margin in the booklet" + defaultString,
+ )
+ marginGroup.add_option(
+ "-i",
+ "--inner-margin",
+ type="int",
+ default=150,
+ dest="innerMargin",
+ action="store",
+ metavar="INT",
+ help="Defines the inner margin between the pages in the booklet" + defaultString,
+ )
+ marginGroup.add_option(
+ "-t",
+ "--top-margin",
+ type="int",
+ default=30,
+ dest="topMargin",
+ action="store",
+ metavar="INT",
+ help="Defines the top margin in the booklet" + defaultString,
+ )
+ marginGroup.add_option(
+ "-b",
+ "--bottom-margin",
+ type="int",
+ default=30,
+ metavar="INT",
+ dest="bottomMargin",
+ action="store",
+ help="Defines the bottom margin in the booklet" + defaultString,
+ )
+ parser.add_option_group(marginGroup)
+
+ advancedGroup = OptionGroup(parser, "Advanced")
+ advancedGroup.add_option(
+ "--signature",
+ dest="signature",
+ action="store",
+ type="int",
+ help="Define the signature for the booklet handed to pdfjam, needs to be multiple of 4"
+ + defaultString,
+ default=0,
+ metavar="INT",
+ )
+ advancedGroup.add_option(
+ "--signature*",
+ dest="signature",
+ action="store",
+ type="int",
+ help="Same as --signature",
+ metavar="INT",
+ )
+ advancedGroup.add_option(
+ "--resolution",
+ dest="resolution",
+ action="store",
+ type="int",
+ help="Resolution used by ghostscript in bp" + defaultString,
+ metavar="INT",
+ default=72,
+ )
+ parser.add_option_group(advancedGroup)
opts, args = parser.parse_args()
- #------------------------------------ show help if started without arguments
- if len( args ) == 0:
+ # ------------------------------------ show help if started without arguments
+ if len(args) == 0:
parser.print_version()
parser.print_help()
- print ""
- sys.exit( 2 )
+ print("")
+ sys.exit(2)
- #------------------------------------------- run for each provided file name
+ # ------------------------------------------- run for each provided file name
parser.print_version()
for arg in args:
- booklify( arg, opts )
+ booklify(arg, opts)