bookletimposer-0.2/0000755000175000017500000000000011754704533014012 5ustar kjokjo00000000000000bookletimposer-0.2/setup.py0000755000175000017500000001134111754704276015533 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- from distutils.core import setup, Extension from DistUtilsExtra.command import * import glob import re import os.path import distutils.cmd class build_uiheaders(distutils.cmd.Command): description = "generate the headers required to use gettext whit gtkbuilder" def initialize_options(self): pass def finalize_options(self): pass def run(self): for uifile in glob.glob(os.path.join('data', '*.ui')): #XXX: do not write files outside of the build directory self.spawn (["intltool-extract", "--type=gettext/glade", uifile]) class build_man(distutils.cmd.Command): description = 'build man page from markdown' user_options= [ ('build-dir=', 'd', "directory to build to"), ('man-sources=', None, 'list of man sources in the source tree') ] def initialize_options(self): self.build_dir = None self.man_sources = None self.build_base = None def finalize_options(self): self.set_undefined_options('build', ('build_base', 'build_base')) if self.build_dir is None: self.build_dir=os.path.join(self.build_base, 'man') if self.man_sources is None: self.man_sources = glob.glob('doc/*.1.mdwn') def create_manbuilddir(self): if not os.path.exists(self.build_dir): os.makedirs(self.build_dir) def get_manpage_name(self, mansource): return re.sub('.mdwn$', '', os.path.basename(mansource)) def get_manpage_path(self, mansource): return os.path.join(self.build_dir, self.get_manpage_name(mansource)) def build_manpage(self, mansource_path): manpage_path = self.get_manpage_path(mansource_path) self.spawn(['pandoc', '-s', '-t', 'man', '-o', manpage_path, mansource_path]) return manpage_path def run(self): self.announce('Building manpages...') self.create_manbuilddir() manpages_data = [] for man_source in self.man_sources: manpage_name = self.get_manpage_name(man_source) manpage_path = self.build_manpage(man_source) section = manpage_name[-1:] installed_path = os.path.join('share', 'man', 'man%s' % section) manpages_data.append((installed_path, [manpage_path])) data_files = self.distribution.data_files data_files.extend(manpages_data) class clean_man(distutils.command.clean.clean): description = "clean up files generated by build_man" def run(self): self.build_dir = os.path.join("build", "man") if os.path.isdir(self.build_dir): remove_tree(self.build_dir) distutils.command.clean.clean.run(self) build_extra.build_extra.sub_commands.insert(0, ("build_uiheaders", None)) build_extra.build_extra.sub_commands.append(("build_man", None)) setup(name='bookletimposer', version='0.2', url="http://kjo.herbesfolles.org/bookletimposer/", author="Kjö Hansi Glaz", author_email="kjo@a4nancy.net.eu.org", license="GPLv3+", description="Achieve some basic imposition on PDF documents", long_description="""Bookletimposer is an utility to achieve some basic imposition on PDF documents, especially designed to work on booklets. Bookletimposer is implemented as a commandline and GTK+ interface to pdfimposer, a reusable python module built on top of pyPdf. It allows: - to transform linear documents to booklets; - to reduce a document to put many on one sheet (for tracts for example); - to transform booklets to linear documents. """, packages=['bookletimposer',], py_modules=['pdfimposer'], package_dir={'': 'lib'}, scripts=['bin/bookletimposer',], data_files=[ ('share/bookletimposer', ["data/bookletimposer.ui"]), ('share/bookletimposer', ["data/booklet.png"]), ('share/bookletimposer', ["data/reduce.png"]), ('share/bookletimposer', ["data/linearise.png"]), ('share/pixmaps', ['data/bookletimposer.svg']), ('share/applications', ['data/bookletimposer.desktop']), ('share/doc/bookletimposer', ['README']), ], requires = ['gtk', 'pyPdf (>0.12)'], cmdclass = { "build" : build_extra.build_extra, "build_uiheaders" : build_uiheaders, "build_i18n" : build_i18n.build_i18n, "build_help" : build_help.build_help, "build_icons" : build_icons.build_icons, "build_man" : build_man, "clean" : clean_i18n.clean_i18n, } ) bookletimposer-0.2/po/0000755000175000017500000000000011754704533014430 5ustar kjokjo00000000000000bookletimposer-0.2/po/POTFILES.in0000644000175000017500000000030511717523300016171 0ustar kjokjo00000000000000bin/bookletimposer lib/pdfimposer.py lib/bookletimposer/backend.py lib/bookletimposer/config.py lib/bookletimposer/gui.py lib/bookletimposer/__init__.py [type: gettext/glade]data/bookletimposer.ui bookletimposer-0.2/po/bookletimposer.pot0000644000175000017500000001136711754703151020215 0ustar kjokjo00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-05-16 12:50+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../bin/bookletimposer:64 msgid "output PDF file" msgstr "" #: ../bin/bookletimposer:68 msgid "" "automatic converstion (don't show the user interface). At least input file " "must be defined" msgstr "" #: ../bin/bookletimposer:72 msgid "shows the user interface (default)." msgstr "" #: ../bin/bookletimposer:76 msgid "makes a booklet" msgstr "" #: ../bin/bookletimposer:80 msgid "convert a booklet to single pages" msgstr "" #: ../bin/bookletimposer:84 msgid "don't do any reorganisation (will only scale and assemble pages)" msgstr "" #: ../bin/bookletimposer:88 msgid "Copy the same group of input pages on one output page" msgstr "" #: ../bin/bookletimposer:92 msgid "number of pages per sheet, in the format HORIZONTALxVERTICAL, e.g. 2x1" msgstr "" #: ../bin/bookletimposer:96 msgid "output page format, e.g. A4 or A3R" msgstr "" #: ../bin/bookletimposer:100 msgid "do not overwrite output file if it exists" msgstr "" #: ../bin/bookletimposer:127 msgid "ERROR: In automatic mode, you must provide a file to process." msgstr "" #: ../bin/bookletimposer:136 #, c-format msgid "%i%%: %s" msgstr "" #: ../lib/pdfimposer.py:102 #, python-format msgid "The layout %s is incompatible with the input page orientation" msgstr "" #: ../lib/pdfimposer.py:115 #, python-format msgid "The page format \"%s\" is unknown" msgstr "" #: ../lib/pdfimposer.py:125 msgid "User interruption" msgstr "" #: ../lib/pdfimposer.py:749 msgid "writing converted file" msgstr "" #: ../lib/pdfimposer.py:751 msgid "done" msgstr "" #: ../lib/pdfimposer.py:769 #, python-format msgid "creating page %i" msgstr "" #: ../lib/pdfimposer.py:812 #, python-format msgid "extracting page %i" msgstr "" #: ../lib/bookletimposer/gui.py:231 msgid "Choose file to save" msgstr "" #: ../lib/bookletimposer/gui.py:260 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../lib/bookletimposer/gui.py:271 msgid "Cancel triggered, please wait..." msgstr "" #: ../lib/bookletimposer/gui.py:288 msgid "Conversion failed" msgstr "" #: ../lib/bookletimposer/gui.py:314 #, python-format msgid "A file named %s already exist." msgstr "" #: ../lib/bookletimposer/gui.py:315 msgid "Do you want to replace it?" msgstr "" #: ../lib/bookletimposer/gui.py:329 msgid "Conversion cancelled" msgstr "" #: ../data/bookletimposer.ui.h:1 msgid "Copyright © 2008-2012 kjo@a4nancy.net.eu.org" msgstr "" #: ../data/bookletimposer.ui.h:2 msgid "Convert PDF documents between diffrents page layouts" msgstr "" #: ../data/bookletimposer.ui.h:3 msgid "" "\n" "PyPdfConv - Utility to convert PDF files between diffrents page layouts\n" "Copyright (C) 2008-2012 Kjö Hansi Glaz \n" "\n" "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 3 of the License, or (at\n" "your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful, but\n" "WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" "General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" #: ../data/bookletimposer.ui.h:20 msgid "Output _paper format" msgstr "" #: ../data/bookletimposer.ui.h:21 msgid "La_yout" msgstr "" #: ../data/bookletimposer.ui.h:22 msgid "_Output file" msgstr "" #: ../data/bookletimposer.ui.h:23 msgid "(None)" msgstr "" #: ../data/bookletimposer.ui.h:24 msgid "_Copy the same group of input pages on one output page" msgstr "" #: ../data/bookletimposer.ui.h:25 msgid "" "Produce a _booklet\n" "out of a linear document" msgstr "" #: ../data/bookletimposer.ui.h:27 msgid "" "Produce a _linear document \n" "out of a booklet" msgstr "" #: ../data/bookletimposer.ui.h:29 msgid "" "Put _multiple input pages \n" "on one output sheet" msgstr "" #: ../data/bookletimposer.ui.h:31 msgid "Conversion type" msgstr "" #: ../data/bookletimposer.ui.h:32 msgid "_Input file" msgstr "" #: ../data/bookletimposer.ui.h:33 msgid "Open input PDF file" msgstr "" bookletimposer-0.2/po/fr.po0000644000175000017500000001736111717526427015412 0ustar kjokjo00000000000000# French translations for PACKAGE package. # Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Kjö Hansi Glaz , 2012. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-02-17 19:56+0100\n" "PO-Revision-Date: 2012-02-17 19:57+0100\n" "Last-Translator: \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-Language: French\n" "X-Poedit-Country: FRANCE\n" #: ../bin/bookletimposer:64 msgid "output PDF file" msgstr "fichier PDF de sortie" #: ../bin/bookletimposer:68 msgid "automatic converstion (don't show the user interface). At least input file must be defined" msgstr "conversion automatique (ne pas afficher l'interface graphique). Au moins le fichier d'entrée doit être défini." #: ../bin/bookletimposer:72 msgid "shows the user interface (default)." msgstr "afficher l'interface graphique (choix par défaut)" #: ../bin/bookletimposer:76 msgid "makes a booklet" msgstr "faire une brochure" #: ../bin/bookletimposer:80 msgid "convert a booklet to single pages" msgstr "convertir une brochure en pages simples" #: ../bin/bookletimposer:84 msgid "don't do any reorganisation (will only scale and assemble pages)" msgstr "ne pas effectuer de réorganisation (seulement redimentionner et assembler les pages)" #: ../bin/bookletimposer:88 #: ../data/bookletimposer.ui.h:21 msgid "Copy the same group of input pages on one output page" msgstr "Copier le même groupe de pages d'entrée sur une page de sortie" #: ../bin/bookletimposer:92 msgid "number of pages per sheet, in the format HORIZONTALxVERTICAL, e.g. 2x1" msgstr "disposition des pages sur la feuille, au format HORIZONTALxVERTICAL, par exemple 2x1" #: ../bin/bookletimposer:96 msgid "output page format, e.g. A4 or A3R" msgstr "format de papier de sortie, par exemple A4 ou A3R" #: ../bin/bookletimposer:100 msgid "do not overwrite output file if it exists" msgstr "ne pas remplacer le fichier de sortie si il existe" #: ../bin/bookletimposer:127 msgid "ERROR: In automatic mode, you must provide a file to process." msgstr "ERREUR : en mode automatique, vous devez spécifier un fichier à convertir." #: ../bin/bookletimposer:136 #, c-format msgid "%i%%: %s" msgstr "%i%% : %s" #: ../bin/bookletimposer:147 msgid "WARNING: psyco not found. You can speed Bookletimposer up by installing it." msgstr "AVERTISSEMENT: impossible de trouver psyco. Vous pouvez rendre Bookletimposer plus rapide en l'installant." #: ../lib/pdfimposer.py:102 #, python-format msgid "The layout %s is incompatible with the input page orientation" msgstr "La disposition %s est incompatible avec l'orientation des pages d'entrée" #: ../lib/pdfimposer.py:115 #, python-format msgid "The page format \"%s\" is unknown" msgstr "Le format de page « %s » est inconnu" #: ../lib/pdfimposer.py:125 msgid "User interruption" msgstr "Interruption par l'utilisateur" #: ../lib/pdfimposer.py:733 msgid "writing converted file" msgstr "écriture du fichier converti" #: ../lib/pdfimposer.py:735 msgid "done" msgstr "fait" #: ../lib/pdfimposer.py:744 #, python-format msgid "creating page %i" msgstr "création de la page %i" #: ../lib/pdfimposer.py:788 #, python-format msgid "extracting page %i" msgstr "extraction de la page %i" #: ../lib/bookletimposer/gui.py:231 msgid "Choose file to save" msgstr "Choisir le fichier à enregistrer" #: ../lib/bookletimposer/gui.py:260 #, python-format msgid "Unable to display help: %s" msgstr "Impossible d'afficher l'aide : %s" #: ../lib/bookletimposer/gui.py:271 msgid "Cancel triggered, please wait..." msgstr "Annulation prise en compte, merci de patienter..." #: ../lib/bookletimposer/gui.py:288 msgid "Conversion failed" msgstr "La conversion a échoué" #: ../lib/bookletimposer/gui.py:300 #, python-format msgid "A file named %s already exist." msgstr "Un fichier nommé %s existe déjà." #: ../lib/bookletimposer/gui.py:301 msgid "Do you want to replace it?" msgstr "Voulez-vous le remplacer ?" #: ../lib/bookletimposer/gui.py:353 #, python-format msgid "Converting %s" msgstr "Conversion de %s" #: ../data/bookletimposer.ui.h:1 msgid "" "\n" "PyPdfConv - Utility to convert PDF files between diffrents page layouts\n" "Copyright (C) 2008-2012 Kjö Hansi Glaz \n" "\n" "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 3 of the License, or (at\n" "your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful, but\n" "WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" "General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" msgstr "" "\n" "PyPdfConv - Utilitaire pour convertir des fichiers PDF entre différentes dispositions de page\n" "Copyright (C) 2008-2012 Kjö Hansi Glaz \n" "\n" "Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le modifier\n" "suivant les termes de la GNU General Public License telle que publiée par la\n" "Free Software Foundation , soit la version 3 de la Licence, soit (à votre gré)\n" "toute version ultérieure.\n" "\n" "Ce programme est distribué dans l’espoir qu’il sera utile, mais SANS AUCUNE\n" "GARANTIE : sans même la garantie implicite de COMMERCIALISABILITÉ\n" "ni d’ADÉQUATION À UN OBJECTIF PARTICULIER. Consultez la GNU\n" "General Public License pour plus de détails.\n" "\n" "Vous devriez avoir reçu une copie de la GNU General Public License avec ce\n" "programme ; si ce n’est pas le cas, consultez : .\n" #: ../data/bookletimposer.ui.h:18 msgid "(None)" msgstr "(Aucun)" #: ../data/bookletimposer.ui.h:19 msgid "Conversion type" msgstr "Type de conversion" #: ../data/bookletimposer.ui.h:20 msgid "Convert PDF documents between diffrents page layouts" msgstr "Convertir des documents PDF entre différentes dispositions de pages" #: ../data/bookletimposer.ui.h:22 msgid "Copyright © 2008-2012 kjo@a4nancy.net.eu.org" msgstr "Copyright © 2008-2012 kjo@a4nancy.net.eu.org" #: ../data/bookletimposer.ui.h:23 msgid "Input file" msgstr "Fichier d'entrée" #: ../data/bookletimposer.ui.h:24 msgid "Layout" msgstr "Disposition" #: ../data/bookletimposer.ui.h:25 msgid "No conversion" msgstr "Pas de conversion" #: ../data/bookletimposer.ui.h:26 msgid "No step" msgstr "Pas d'étape" #: ../data/bookletimposer.ui.h:27 msgid "Open input PDF file" msgstr "Ouvrir le fichier PDF d'entrée" #: ../data/bookletimposer.ui.h:28 msgid "Output file" msgstr "Fichier de sortie" #: ../data/bookletimposer.ui.h:29 msgid "Output paper format" msgstr "Format de papier de sortie" #: ../data/bookletimposer.ui.h:30 msgid "Produce a booklet out of a linear document" msgstr "Créer une brochure à partir d'un document linéaire" #: ../data/bookletimposer.ui.h:31 msgid "Produce a linear document out of a booklet" msgstr "Créer un document linéaire à partir d'une brochure" #: ../data/bookletimposer.ui.h:32 msgid "Put multiple input pages on one output page" msgstr "Placer plusieurs pages d'entrée sur une feuille de sortie" #~ msgid "INFO: psyco imported. Bookletimposer will run faster." #~ msgstr "" #~ "INFORMATION: psyco a été importé. Bookletimposer va fonctionner plus " #~ "rapidement." #~ msgid "Sélectionner un PDF à convertir" #~ msgstr "Sélectionner un PDF à convertir" bookletimposer-0.2/bin/0000755000175000017500000000000011754704533014562 5ustar kjokjo00000000000000bookletimposer-0.2/bin/bookletimposer0000755000175000017500000001212411754704276017552 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # BookletImposer - Utility to achieve some basic imposition on PDF documents # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # bookletimposer # # This file is the main program of bookletimposer # # It contains the CLI frontend of bookletimposer, which can either work # standalone or launch the GTK2+ frontend. # ######################################################################## import optparse import gettext if __debug__: import sys import os sys.path.insert(0, os.path.join(os.getcwd(), "lib")) import pdfimposer # We need its exceptions import bookletimposer.gui as gui import bookletimposer.backend as backend import bookletimposer.config as config gettext.install("bookletimposer", localedir=config.get_localedir(), unicode=True) __version__ = "0.2" def main(): """ This is the function that launches the program """ infile = None parser = optparse.OptionParser( usage="%prog [options] [infile]", version="%prog " + __version__) parser.add_option ("-o", "--output", dest="outfile", help=_("output PDF file")) parser.add_option ("-a", "--no-gui", action="store_false", dest="gui", default=True, help=_("automatic converstion (don't show the user interface). At least input file must be defined")) parser.add_option ("-i", "--gui", action="store_true", dest="gui", default=True, help=_("shows the user interface (default).")) parser.add_option ("-b", "--booklet", action="store_const", dest="conv_type", const=backend.ConversionType.BOOKLETIZE, default=backend.ConversionType.BOOKLETIZE, help=_("makes a booklet")) parser.add_option ("-l", "--linearize", action="store_const", dest="conv_type", const=backend.ConversionType.LINEARIZE, default=backend.ConversionType.BOOKLETIZE, help=_("convert a booklet to single pages")) parser.add_option ("-n", "--no-reorganisation", action="store_const", dest="conv_type", const=backend.ConversionType.REDUCE, default=backend.ConversionType.BOOKLETIZE, help=_("don't do any reorganisation (will only scale and assemble pages)")) parser.add_option ("-c", "--copy-pages", action="store_true", dest="copy_pages", default=False, help=_("Copy the same group of input pages on one output page")) parser.add_option ("-p", "--pages-per-sheet", dest="pages_per_sheet", default="2x1", help=_("number of pages per sheet, in the format HORIZONTALxVERTICAL, e.g. 2x1")) parser.add_option ("-f", "--format", dest="output_format", default=None, help=_("output page format, e.g. A4 or A3R")) parser.add_option ("-k", "--keep", action="store_false", dest="overwrite", default=True, help=_("do not overwrite output file if it exists")) (options, args) = parser.parse_args() if len(args) >= 1: infile = args[0] preferences = backend.ConverterPreferences() if infile: preferences.infile_name = infile if options.outfile: preferences.outfile_name = options.outfile if options.conv_type: preferences.conversion_type = options.conv_type if options.output_format: preferences.paper_format = options.output_format if options.pages_per_sheet: preferences.layout = options.pages_per_sheet if options.copy_pages: preferences.copy_pages = True if options.gui: ui = gui.BookletImposerUI(preferences) gui.Gtk.main() else: if not preferences.infile_name: print _("ERROR: In automatic mode, you must provide a file to process.") return def overwrite_callback(filename): return options.overwrite try: converter = preferences.create_converter(overwrite_callback) except pdfimposer.UserInterruptError: return def progress_callback(message, progress): print(_("%i%%: %s") % (progress*100, message)) converter.set_progress_callback(progress_callback) converter.run() return 0 if __name__ == "__main__": main() bookletimposer-0.2/PKG-INFO0000644000175000017500000000147611754704533015117 0ustar kjokjo00000000000000Metadata-Version: 1.1 Name: bookletimposer Version: 0.2 Summary: Achieve some basic imposition on PDF documents Home-page: http://kjo.herbesfolles.org/bookletimposer/ Author: Kjö Hansi Glaz Author-email: kjo@a4nancy.net.eu.org License: GPLv3+ Description: Bookletimposer is an utility to achieve some basic imposition on PDF documents, especially designed to work on booklets. Bookletimposer is implemented as a commandline and GTK+ interface to pdfimposer, a reusable python module built on top of pyPdf. It allows: - to transform linear documents to booklets; - to reduce a document to put many on one sheet (for tracts for example); - to transform booklets to linear documents. Platform: UNKNOWN Requires: gtk Requires: pyPdf (>0.12) bookletimposer-0.2/COPYING0000644000175000017500000010451311717523300015037 0ustar kjokjo00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . bookletimposer-0.2/CHANGELOG0000644000175000017500000000156111754704370015226 0ustar kjokjo00000000000000Changelog ========= 0.2 --- ### pdfimposer - fix crash when using numerous pages per sheet with few input pages - fix unexistant variable in StreamConverter.__get_sequence_for_linearize - fix baseclass call in AbstractConverter.get_output_format - document private methode and cleanup code comments ### bookletimposer - use gtk+3, glib and pygi instead of pygtk - some Gnome HIG compliance: - use big buttons with icons for conversion type - remove close button - embed a progress bar instead of displaying a progress dialog - make and q close the application - don't try to import deprecated psyco - use convert button instead of apply; this fixes the "same menmonics" bug - help: simplify legal notice - man: convert to markdown converted by pandoc - fix calling unexistant method in ConverterPreferences.create_converter 0.1 --- - initial release bookletimposer-0.2/help/0000755000175000017500000000000011754704533014742 5ustar kjokjo00000000000000bookletimposer-0.2/help/C/0000755000175000017500000000000011754704533015124 5ustar kjokjo00000000000000bookletimposer-0.2/help/C/legal.xml0000644000175000017500000000104611746107426016732 0ustar kjokjo00000000000000 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (GFDL), Version 1.1 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You can find a copy of the GFDL at this link or in the file COPYING-DOCS distributed with this manual. bookletimposer-0.2/help/C/bookletimposer.xml0000644000175000017500000002307711754454200020706 0ustar kjokjo00000000000000 ]>
&app; Manual &app; is an utility to achieve some basic imposition on PDF documents 2012 Kjö Hansi Glaz Kjö Hansi Glaz &legal; Kjö Hansi Glaz &app; User Manual 0.1 17 Fev 2012 Kjö Hansi Glaz This manual describes version &appversion; of &app;. Feedback To report a bug or make a suggestion regarding &app; or this manual, please send an email to kjo@a4nancy.net.eu.org. bookletimposer Introduction &app; icon. &app; is an utility to achieve some basic imposition on PDF documents, especially designed to work on booklets. &app; allows: to transform linear documents to booklets; to reduce a document to put many on one sheet (for tracts for example); to transform booklets to linear documents. Usage To Start <application>&app;</application> You can start &app; in the following ways: Applications menu Choose Office &app; . Command line To start &app; from a command line, type the following command, then press Return: bookletimposer Main window When you start &app;, the following window is displayed.
<application>&app;</application> window Shows the&app; window.
The &app; window contains the following elements: Input file button Click on the button to choose the PDF file to work on. Conversion type Choose the action to perform on the selected PDF file. Available actions are: Produce a booklet out of a linear document – to transform linear documents to booklets; Produce a linear document out of a booklet – to transform booklets to linear documents. Put multiple input pages on one output page – to reduce a document to put many on one sheet (for flyers for example); Copy the same group of input pages on one output page To copy several times the same input page on each output page. For instance with a one page input document, you may selectPut multiple input pages on one output page in Conversion type and check this box to obtain several copies of the input page. Layout Use this drop-down list to select how to dispose input pages on each output page. For example, select 2x1 to output a simple booklet. Output paper format Use this drop-down list to select the paper size of the output and thus the scaling factor. Output file Click on the button to open a choose where to save the converted PDF file. Apply button Click on this button to launch the conversion. A window will pop up to show the progression. Close button Click on this button to close &app;. Help button Click on this button to display this help. About button Click on this button to display informations about &app;, its version, etc.
About &app; To find more information about &app;, please visit the &app; Web site. This program is distributed 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. A copy of this license can be found at this link, or in the file COPYING included with the source code of this program.
bookletimposer-0.2/help/C/figures/0000755000175000017500000000000011754704533016570 5ustar kjokjo00000000000000bookletimposer-0.2/help/C/figures/icon.png0000644000175000017500000002271611717523300020224 0ustar kjokjo00000000000000PNG  IHDRddpTsBIT|d pHYsruiQtEXtSoftwarewww.inkscape.org< IDATxyxŝ?sH%[/cc.cr,9IHްg6&}“]!0̂cmٲnYGnj#iFҌL6 `¼x5aVh6]3?> [/ ̫TZod֏c.dqh1h[j[YjUŎl(!=.ב]پ.)}H_mU62B[UU?,@-]Q؄s1rWKĿcV>tY*lS*ʵ"[@T,o,RUnlWiM lBʺ%,4?:>a)0}eE˦6%Uq\Me#8ʁ"+Lsʝ ,Dj핐?F)f!pg ڨWu&ξ >0ۀb_v .mgJtc"%=dlw:ߞrF'dѥxB4I]?4 8,¾sOC[L@vJgF(:$)ZXZ F?!k/D$!XXr1~@m_4c1!u78QTnv!@gTk1BsK2A ׁXZY?r&<Ȇ-oO>*ubg^R?mm%6-Ne{* | )D8d?`ojr%bBjMɬ.$꬙U#%,VL$I'SևlzF&ꒀjM{s4E[g7+)4ti(HY}'ݓUڂ\҂;E͹yLP(J!_R;++o^n]lI.d $ٌZSMuқBH~$;.yW1Uu$dT{UճE9]?[(yR|@*6nw8TEU:!刺wF{cK1iB!ʑk!k"0.[:ͯs-K~wU;_ַ^ɵ W!0O !?!.Wt}5B\-5ZG~^v+.N'vÁj[Ν :R'M{Ԫ)N6#V|f%KXtyʁzvn>7qu;%;EO6DBRHiGx:2J].~?B[ne7v҄!22O Xo J3( sϧn,w#oߝxә/kyj"[2W(SMZ4Eeχy=𭟽喇'Oш^qR|׿hgym8?=_]t#HPRAAq*QTDB0FWqH;-v@qQ@usBIOUevEaG1͚s"!@ 8sc^mFlv;2jjkK<4!l6 9uBI݃''%q% '~>hX,<DBkK }=e(t:O6=m~)e\VU:''|RuݔLobR9w.vWW_Z K0zt$f̞MyEG_*eWIuxi9 2@to4 PhBTTUq 7dRk?*pa֍oJÇiinN`۩9Oe%ycr2ß D( 7Ǥl2d8<,u`4(*.f 7㏳*6tw/ʦ =9tGDlΜ㡠07S' B!II.=d!b$Y!d5<Es1cWwD~)ZhRڙ3)*)p^D"ф L!_0nr=s! dr Y\̊+ŧF'Lnf͢:g k4N!0G!Riڱ2P=ztxCѦUUBsػE5M{k+m--q!h4OUM y ib4iYP%͎%F)S66jE)(LPw={{3Vu]TWmt BPXTԚOV/C( @k!1L(JnRVWwi]M31ze(D+R&uDG[h!%̘3ۍ9a~G l)/N$!zzG+32S zPs={!Gbp`M(qp{޼v-xy;P(D8$_ IZ%.  DL67̃ b?; ]fтx*+K08|W} 9W@4k#:^/_ˏ~@̝~}ӬsTVƣt<90&3d/FXPr./tx<<8ZI g. qh~N8A3q-6O-_Jɑ?==[z '?ȟ=+)]ii:tw-%BQzs&$a6!ZZ0 #z7n^̌܉PȐRr1G4iuu]Kq @ߦ!qORji3IM^OM y=gB&c6IEaڶ 9j8q%#}:[8/o?ûk7nZZhkk&5a32^ MB#LT2t=!D~-L˗#,˫бkl01Ea>q F# 9)S_kw QU CA û}l_lny=gBD,V&9)C|qȚ5ٷhLG p^~p8LUu53hC!ؑ#Da p!ee4!޻19 W2S$DӂCf2?')/ɇoߎqbT'r~rP5*aƺW~  zD"ĢQH|C"o^!s"ͫVܴ)~yWF% Q93ϑChin)q{H$}8~BLʴZRw47+4}E)+*"//G~>yyy"Dѕzs&3N@LYONfΜ 8' Q1e :kTλ_* 3֯zvN24LN ·zraBocn5p8L,ÚC{ٻ{7;d iN2e_iÓv.|O\x3 0LH)n{"/"^"զOG-;mn0]v}~#_x=Z/ˉF{!eZ]]aVxc|9s?s&ږCFM GBfcVxǎaʕVRa`feR#:je%82]Gˋ;8-VE\n7s8t45 ڝͦ>F 5yax  CE]g…D "HPzr"dRf]'m[T),0{lǃeZOO~dtCMElBpVzNBJdYTD^~>J2U((( H" )soRqbň64Iؿ?f=vhm-.Lc1۳ 4ө/Ś)xpiTUn˓!^' bDN[SO=th*WDBd@&81I׿HrԩS~;E~A3f)hZ苜Bd&DJ<3,It͞6u*C?e4ݧNwn(*)aɻkw"_ʴJ 3g*/E{C&"93RbMQBoA E3g( `*-E2c~&ӥص %ٶeK[ edX7P2280`h4zZʊFq{<=ѓ fuRc2?_'HuaL9s0̞=cJ~D z0׋Z^ZYVWo˖5bsp?xW]I+RK.fPyikmԩ!KMx $Ia!WŰl,-]z^{mH Mbc<ܬjpim\@ tBPYUE;;ycD2 b%i^JIϩSښ ,V+8p88lฑ()3 Un\~?͛ o:*vw"/7M7AC!b收unʛ׮%$D sޣ[=AB89TUWx$ǁ fEI@=$oX_mق $aJ݊+; ;WvgRZ/p$ǎA4Mz ]n7eưNmy"kBf[(A=FPfM7YYM EY CZC0d}k,^000_y%2#qxeT;B db[=?@\W7m"Q^Q1a;0X~00*}]׉bE^:l jGr&dlؿ8 +66yoxirKd[U(ܱoe ۿuȆJʘ>cFZH: NG[ݤnhZ9 (yUɄb9&Db7|sƉ6~)@(&E0_yed^2^[8g!JՍkbtwuFG[[-lTONab_>6Q17be ,fWt%9TyE (\u9g-\8悜P(D{K /CPN'ӧrw4(ʘӬ BLU~7n$ۣhӦaYo ec$my μ/LeUUlmhɤi}h B5jB'&"geFd?HYaZf3u0s(pY(.W- d,[Fv&UElT:mkhEQ2 άL!wlpj8;>EN>yeC~q<_4Z$c?z@ dbL6mŠ_$&ߟtm2s矸/}̍7&DQ͓< #/g =bۧouӋ|bs.Z8,=pnAΥr2JG[ӁB6e*EĢQ¡xt)Țh|'TL&hjl X3(up*+vO.7Q[Ok3Q B(b1>LáCeRT\̱v;TV2o"TWgwlY??{K۾z $m3w|MKZsSF9H#}> ڴ>R >]h6X,'SvJKX?RTTW<.\H}g%.d9h)⩿͗]H`… y!qɅbX0q8}>9BSccrr_xTL@"$:"p8LSb-i[1?A5!!ŗ]6庮 "?SNq)BPPX+`}{믳sv^ old2r(^ {C~^_=D@:HoO ֆʹ ٲt]?=G&&%ΰ0 lsefD: łb$%~:`~V+55̚7m2_=D+m>/bٟ6%tE:#8P_OsSQU]ʹ;A<@{hk;R$,.h0`0hĐHKk1e0\2)r¡p8P>֣ѨڽHl4,f3L2U|YOxƑP~J>Ԕ+7JF=|uOgƬYiox8rpr?xݴ:\n7EE |>`D@Ð1F:t Pl!BzL%lb)EH)Bb[%btQB:N***@f7pukXPFB>߰I>ػ7.\̙?6|`#qښ>#Պ  wϞd/q}&sl /Z |Mg?я%K P)uVJd@zU{b/&M3q?IDAT,~䷈4JX0H8v/[kc}{t8z,j O_J8jŞGԩ؇OIESMGks3Fy%YqdMȺu=ܣm{u=i7;-]eAt]OF`*)5 ޱSh^MUAsh6Ç8c;ۋhbjL&1)chT|x}/!zu)p"GJ9jKR!4lV"ѨAڈTh,f4__>t{OXA̙sDWG[^}v4łhpɀp4. ,蓺'7(}`'KG*|IK^^Gb:x)=RO8*BE)BWZ5zϨ_#de׌Gl7ol/t:nZB! B̙?"Db8bǛoo!0Y,vLVk\P 1!vZr7w,[.Ih0և(uþS_}H0sYE:+~mšn ƍ}> V{~>feV>a>dW'dC1Āׇ}\^~OW׏}}BUU=gcVHlNl>/{C_ F}wnX==^Yymo4]EhP/(, ý+W4B6mfO@.]}3E`فOoV'dі,#qa_>>8l0ڊWcd;Dg|ѿ!67 "1f8V d\w2Ƥ `'c >LkcRl0+2poBI#g=dѦ=L~}ؗ6>ȹtӤJL ;aRCXmnZAw ä'a߻#AD;em0..\1yP21X1IENDB`bookletimposer-0.2/help/C/figures/main-window.png0000644000175000017500000005634511746107426021543 0ustar kjokjo00000000000000PNG  IHDRdcsBITOtEXtSoftwaregnome-screenshot> IDATxwXWlE,қ+Q[&EMQ1MA`o1󪉉%6 *MP J:3u z~ϸ-[<{"UP H3-Uy4s`Y}M TotHv?7k(*mJyQU*I<.ѮE3d+Ld {fMR(1P NYEmyeM Lߩ[kU3DOj.:otބI{hVUC,+).K , ALyD:+Ԑ=;[f"x&œv=#-nێ_Q10z̦Uy4[& /모^>>`Xs+ZR’O YɧZ{h&,V-7lǘa lqnBJ,=t׫$wN|E W`L)zM)rebdֻiCK}MA<A kɬ92ol$W T6+RZE p8| '<@Nrh8|A-Nli&p@lA،P׿t=^ uCT%TH)=A٢ m%iK$I*1;h72uDJڬ!} ψ#kAY ,u%l,QMߧ.295!jX4(|++ ak -$Rj/^TTD(9JrZDjitwpsyL?*.dn.ޞgi=Ⱥ~^jQ4  J2ݍxNJ:A}CpUhT&oa%hYQQU\Z&W(ٶxc[EFIEU΃Z6ڶ~XP$SF63Zj6+jax,jk.f#MQRw@>ԪE A۾+yOo{ z0(g-WI%e_κ۩?ywpZWJ]Ɲ(;9y^+rbǟ7ERtf~[PaG/;sN'D _7fUjߩ]mgmC) 72]@kǿڊ| ⽲t+;;:wkLY|1nmؽ^":an?g3)  ci0,48ja&ZxXhF ,ZҒʬ,PɓdA-Zld\" # JrS ɔ;E%J%9$}D]'JtrN1 (U\G*WbIs BLTo9#&6kk]^Wg诏wucWr|81[Nջv%}:jOot_VWjZ{E}uL"CL/2$-MC ֐1D?<$$HbrYWck>Gyו99Jǡ憤(|KGށC(HG@%R#c+Ej<=k[z{M?/)7MKRxA5F[[YIEO$v-ZY mQ2SC|gD ^y^n%ZXXԶvcAzvWǺ;T-V[bckt29ĵ\OgnmZ?[W5ΈD՜o)C<[Օ "!F*>cՕu9nO+.^~y҇k+RJ5ՕUyM >̛<;pYT iN:Xi9h|bn>-srT;Yt4ʢO'ճ_s>˭*š[v@fŌݜu"5JCYM p8:ESM!@RQtнw%ƞ֓4p(hʒr?o}WZ6@r9'W3 W`Z7gi\',}yǯiU迭r)gOIBygQByrQ}w- +Ȭ L?ddBI֪jh[QMTt pD5{j$2;7^PHdMV A^QʞTfsFcI TAI`#5M q BļA+ yV A Z1A^S+<色R(! \phqTnSbi)*XGƾATp7GUR݆ b(TU<~5|`; ,-Z#ČHe3>>EVhPVKikM bX ,ܵu%}4(HQ$1=;I<@@Q!ҒbZhW޻^S[̿\.^tz"ŭ_ ͠LZ1ĔϿv>[9Q*2WW6_ȋAmDQE r8&j^V,))ibL,bHsh@ee}+jT(I%I*J%M5UÇ:w;4dv--+epS?(,(`U6.^:q_Y6x|_[>&)yYeWlP@e %"1q'EQMRθ;?[rptjM`Tda\/9 3 JJ:ڿ_(PEEr}NBWWߊܚѯ_?MKB%|w$IR$I*}&[u%+;&+֪NW̌7W\AYlO;+ga4߂:!Fo^s1T5/#im]B@$yy)$)W@W{VJp8ssHh:*x=HJ<^5T[T*kkkҒbRoOөPh{AA*ˈ 6G'aΝ=z 8(-= ߴys=<ΕlZvOX( H\ly=!ʘpT6{t7gvm7mE(4^uGRID5599Żwj]dfVUWJ%uƸ .\ѿ=zttt ~ nHVZCN,.U4.'7lx֭ӧOeg KRy0b   UgZ^)a>jڛ7nI|''J`dQ<) >|$k׮j̫ _NUZZjQryX,usghS (wjǣ(RI<-֭]koos^lʕ+ŋ!޳}nnnxѢ֭mzCN( /_Bbll߾LRѿ7Ľ'tv  ym՚`)*|TX\\Mlռj,]UV͘7.q(lO7D F#d94;YUYM*Ic8+Ƙ0R^^^MiiQ2 ((/q'iZH"U=s($IQ@h *_P HCO\nJ[ۥ+V >n^5=( ,[ lV\sE`V*4?I[9zE{+Mӧ=9/z΍yx : LJ3AٯT|S+rɗ؁LO>c4Ms|6>~L\V?v&s[lH$EEEgݻw|0yrttLJ23iL| 3{!Ckjj=s7mY\\?/&FBE.~pje.BA$Qg26#_TSS_,Ys~e;c‹K۴8:)#N~//_M[1jyXz ZMMo &|_|ӧg-[Θ5lz 'cƣhr| |(jBNP4@S 4ZR+5Y37mx^5iʵ&Ty!@ zܹ,xa܄pmDK~-Qc6ӘIsT@@E4(hhx\ؼ[Nc‚o#)a~`>yQ[ KAuA6/WFV*Y70OI$I$I*rc;bR`:d**4nUoh[V/2/WF~3gV 1 -:Wт\A?q-wA-$F+W{*]>I3^y֑ٵl Z14ph*("))C !} psplCLAn7br78 Z1Ab7h1oЊ!bޠCļA+ yV A Z1Ab7h1o^~+$tt64bRtÆrnҹKױocr͚-hYay*++³W\aaa7C9.ؚkSb~0yUeKQƍ{lڽG Y_'k_pέ]JJ:M)..vncf[^]\ݺuM:F?Э{'3\xq^c~ԩӪ)^곢999B^>LRlߡݻL{֯{}vVȑ?`1czӲ+֛WشijK/9}jggg'o=$}3 O;omooeօϙ0ݥK}IY.^J`ׯ_~w9D WvfW&Emڴ5jTMMgΈaCmۖ 9?GHOѣǂ;v0zk !QfnںLl`W7BQR\iXvPPPp;3ٹs7oYLzZBpqu#B,*̼2`@NΝ!n߾}>\ǎz|0~mRYiw}|rб>PnU7{sNΞg~8¤LINyy|}|_:j !}s1ggg4o6B(**RM BfթSgfNMKKMM}vHHHǎѣ"ջЯ?JcM,%8Czzz :ٳ&QO/ȼzZMMѿڥKHH鍻;2zk !mxc4~XƉb 1}ݻ{GpwwۙL,j9z肂f_-3vhh+guiU?UUU%J/^4aD&vܸwod[{O#Fxyy8~>|8>c Xux.]n-}z',I~20͝;wiqq*r0rQG9;;/[tڴ 0zwIwdi2SAR}.4M?~ɓ'75aЫ XXXػw/>uAWb&9qV\K" W7h1oЊ!bޠCļi,+FQVRI'+ ~LӾTk_xn{OPb8\*ʾ{ ҥ[ kk"͇ŋ]zĈ $/yC0I#trz+< ;{F~ݍ$mmm vZ'GGk*`BPQC i`htV+J*g`INkoaaaaaӺs(#B2] IDAT^gZL&cn /[1T!:2L"u֭[nqqqdȰvvv)| rV\qo޶ۮݺ3/dDGEGds<<:tyV6P(.l׾_|$l;{xN6}*&LθqK~i:zxzE͝+˟*My-,nҵ;iTPmilzґvSIsg.nJKOQw*ehk+#G0st30ͽ_˗0/Fgy[wu4V_wj؊)BB%СCvܹ|r00-Ī6_KNI>}+V_v++WbҬZL\vFJҹIIIzXvmVVӧo$?z ܰa[N>u[ $$,w'̜9NvVVm_x7RDիV3ڔpwn3kԖYh0ںZ.Hzґv˅ >{GQwݥ"UmmqsGso1Ə?q8{?',,,:FOu4V_wjOʟ}e~pvvqL&[t%˪*+fgⲲŋTTTy$ܥÇ ''',<"=-tv!___&OP0#Mm}ڭ8ئMUz<?DY3uTY"U.ۨait(-Iv6l󮀀*hVǦ4REnj:: ݽ^"騻RF*F j9:lFO/GV}g0|%к/̐mll ՗lD̽7R///6\%%%uUU^4!55V[`*--խpmǏgMڪ c1VVM!VVVJӯ]G)Mh9*q耱YjzZxEq`ԨQQcACZ]I;WE(>|cޣl8{<O"0lx֭T^o@)SN&>ȽC~~>[mk #G:tHu(mVV(mn(EVA# hHu܊۴?w4O"ѣGqL'GG>xT*33oO6RT >d5Tx6嵅۟G޽gƍjEh޽{FV(mn(EVA#G[6:/&bΝ=qjŊ+Vʊ^~gqqBga`ށz-X/XkתU=׿~ G9jw>]B ~ࠈHO3f5+,,^қ͜\5+RokΘ]ҴFMn^wMMudAH+ kz hDHuc_5Hjš/c}4wMիF#@+.(_>]Stsш>4&x| /iWI[WR]ЗO:hWF􁤑W/m4wMիF#@+@Зkjn^5RW/u<\j$A @BļAH7~1Ab7h1oЊ!bޠCļA+ yV A΋Q%ʔ2IS@<[ ,"~y A^08Lk!H1oH/ aL<ƣm]x$AkhV FC|)u5FQڜHY06mV'?խG@ϟ]W4ֽ!y i:X2y1Hu= )BC|)=R V(m~V\UYYy瓮\^fyuKH[אo%s隗d蕬#F7z]h@K1A4REO󈏷7Gwu17jΨQ4*ƺ7$!@Kf5/1fⰧ!hbmtp9)--xkOOOVz3q/׬]gkcbÇ^H5`\<| 5+N/YSXJ(JP_P[={vZfU^אo%s隗T7 lH߰ HK_hOdd…U=ck״iӳ MO녨!y i;X2y1Hy@Ɇ 5FQڜ,mimݭ{ի]F?iwBo}[tc5$!pK5/=C&,!޽;ndhr]@H??_./\hԨQM5$D+^^}R#bP_2#Mv*_Q"%_ A Z1Ab7h1oЊ!bޠCļA+ yV A Z1Ab7h1oЊ!bޠCļA+ yV A Z1AȤ2\I lmmf[{pG*,,D!Y1B~#%ʕKp}FVYQa:ݐK֮Y=bp#4 F׮]YB`e1^*,_haܽ{w.\ԩs֛X712dHp75v_m]cEQLH{CC\rܵkVњ"ML&MhEYs?K LL&$:/::F&{$ܴys=<ΕoVlAAA]*++G'!0$#ә@$-[޾}wϩӦUWWUqquw3&Lθqb-Ğn\|_')73JYxxzuil]۶}۵[w'SnQV+\c;k+T: !J[hkFm]67$!ĨPmͨk"s""5FX׮^)(,Xru nHVZ 111֭(In3ڲYoX:pGso1L o޺u !ai]f͞=יwߝ0s;YYYWͳ>|?1cƍq0~NXXXt\']|E5*9%SbQF&UCLZlH,z (J[hkFm]6;!ĨmͥkboomY+ib?Yr.<=]9|rrr#RIxU___~XxDZ-:3g3 z\ջ; H||JG@H$ u;SMn{̍3j(777UH$=zdgg1ݽ{xz>Un󈏷7݇0#=Eoө]cpPJjb=u8ސz ps8eeeD"7s-L^^^Mii)s?/&zݺ$I^fnT:ҙ+++Ref:vb纪331&kxIUV^ΦglSڣQ喖zzx0Q M MJ=dhlgC 5f[k8iHg1KEX:1J(>|srrb|yĈe˖_~mҤR֭RrXĬسgkVSL:ejFzXT >m8C }~~6QښI$\Ȃ&5DfCX%G5.ݪ4qk81va.]a>_Ӯ]?)))?_ N, "##\ eeⲲc0ADl޲e^< eݻwOJLR̼=uڴiMP(h&ɧ$R@`i)=|v!FFF,\\uM mM׹s-[J$yfؤl զ(J[hkFm]UiHאqb۶5zyVSz~LT|\Yثw`...q ߣGCll8?~Ʋ̞=xPߤs"""=<Ϙ1ziFɞ^ K- ==ƒ 6u_ׯW^ڎ8hk7=zo!!!Y5^ Acڔ}Eimͨ 4v* ic2Nu\F/o˴C֮\xɲ:c+q"##DFfݻwǍpQMrjф6D fw߰'(xEڎr>Ap(ڽgOnnnDs/ qΟ/.\4jԨV\flk bv #L@mt#tn8U^^}R#bаC bڮ1hE  yqAb7h1oЊ!bޠCļA+ yV A Z1Ab7h1oЊ!bޠCļ1bb4ME4ABr(biRQPPqSk7AuǛaCbi I %C||pܦ1c Ńܜsg4׆ɛ- Z14P2#=}Р~mZmu Υ[ZHiix䉷_S+W/ j]s3g&''0yz˯A^ބ }7N,oy?4:wdDGEGd2&ڜyd?qFr1Yŋ0{~Msٳg7ȋC*رѣx;vHzˬ{ 3gθu?>~!Ĭ[(&ͺg̘nkkb׮^z`U:$E'sLW HHXRo I*Z~/:o޼CP ~yRR̙B!WM/ݕbW^KXV[[ / D/IXzQQVVV "N^ZhMUIJJ6}oӆI trjU+W(1G+빢pʔSfErﳻw#F/[k& ‡2yyy̤ x~WXXxP \.oqlH|\Yثw`...q 07n8zQCBBsfhP?M b:n_1iix䉷_S+UXXX&5.F:چĽ{.bFxkV CإKĆ2Ȋݾ}{^>^>Ə̼7!j50{#9dȐYblz~zKK׍ž<ĨݻGEE5ܐb#GHOHO9rdDddnnn 6Gd2oj-;tHo$I%K̘1CcF8$cccϜ9s3g&&&ꖠVl͚gϚxT*33oO6MoS`AX,ű DFF] mnfM?ԁzɆxyy4MWVVTVV1lTI4>i:$F?xѣG;uҩs?iӆݸqѣG}|F3{!CU\ ׯ_]6}1>~WXXxP ?xnppPDD3F)T: {%nMy,ynnԩS)So`maLĉ1`@#&N[nR+ʌ6fw̏β HzBF޽O7n0qD~q vpeSk4/4 &ϯbZ ] چIF b&\+ /!ui!s1Ĵ\ QbNW5{HCLA5UD<] 9@$4Z14ٕvq՟A TTڪU+CLةӕ˗: 9s)((Z,*zJn]CLHƍʊJ wǐpZjյ[Kh[iN*A!J+^Њ!lj-W yV A Z1Ab7h1oЊ!bޠCļA+ ygA$IQ$Ii(Ap.WB+V*i76yC]ǎ}y||B I %C||p]HP(rsΝ9CӔ_.OB+Rf4ϿmS나=|>mt񼛻W >bhR;A4EHE}WZ1K32Skjo4 4urtm#trnjr¹B^dx7VI\Z1;0ȾjRSn^оSS4{oBӆU?u}畳bIIISMŪN9θ**طr&ITRT4]SU;|sOSձC&TxJΝ;7iҤ|mf6]d[%n.YeWlP@Q(̄$ɜUKڷ8>ܺ5mz>M6M $2.u\A3Ȋݾ}{IB¥KoŋwQw322ܣ k( P5aERER:u쒖:y<4$o>bĈ4}{\\50dt; T94>X~+<G}}}XvJ}Z[e͝Z||N5Vn_OvW[[/˅777XhQȀu6FAFo!G?ÀCp9Obɬ"JB!i;V~Çn K&aW  oݺ͢WѿQWbRoǎco ֭[;r˗17lPQQsVXP?裷zkΜۏ?V5ik֬9rҥ 믿]رc(̩yMM M0'p{ +VO\.W.7H$ruueCD",boJKKn EEEA}G^BQ4Eg,8M($EQ_Gz>ٳ{͚5˗]fQ#m҆boooBKKK@ooR6s/J%EQmw?3fzyy1!^^^%%%}II FhռF֊hHWՅw9fq\eP @=ǓH$̽ Ç|vrgxviݺuzZ*\"ZUQ(ry<.x<>^ ӈ8쬪J檬`{wr׭[1/V\PQ8k֬[=+&7hb JtG}3"URyر춶V[VkV;SY8:qG-7ލ1Igw9w9痛sA-3SLmMMMN0F7»B!=e~5a?oNGϷvn6<$ ǹώ(]aߏ='fg_kᇥwݱ pI}i=k-ΑԬz}uuMp:pBBDB$}F DP^փIe^nذAʬtUUU=--fxx!#ʚKkwݝGrrr)(*;;'99HfN,Y8n\-/Oh4Mnn^JJ m_f m(*''(׏j>Y_lu;B @~vlG'O9s&2*:2*'NP(̙3S[bLm[.Y7xeOϏV[#۷g*W'M"+V[tANaPHܿ{rLH1wLd؃33U .  YYΛLL\"MOOOLL ֭J'UT[,kFnnnDzj̘ɓ'BdBll\llĉ҂f +&Q ÔJe|2**:((p.5m%QQQJcŴZ-B֭[zyZP|v%Bh0 ;8{8 С@+VX!^z/]$IΘ)*'D67h6`liiv3KN}\!tƆ~7S ;>9A+eA+eA+El07/^>''G5"h'p\=)4ԮA+eA+eA+El#uwwx=˧1vZq5P(;`FDFс'dVZ+-po p!f 9S0yZq-TB.~epoF4x{{< {婍u7oH$??'NڣQ##(`0:th߾}eeeR909 n +y`?k[lҥK;;;8PYY)Z!#с咵92rbgϞ ܺukppsL$qơ!ڨj7oeVKE"iY%c0'Mnݺ^ "ȢĞ={=wJ<ֺٳgcccÏ9BmXֺ {ZxڿL&0\;t֭[1 8xuuuE봱ݻ555ͻwf\᭷޺vڥKZ[[}||jy,I?>%%={_p6rQ}w$1 S&*Q7 \ʖ;;-m*'hhhX[>>>Zvvԩ=/?+ n߾|yB]]-a Esg1 [<::@?S3$\r/—Vf=fN7'f:ujiQ5wn|cc,k@vvvX+dt֝Ox+W2<.ʁb]`m^|O?缫\jmi(/4Il4"'7//hoo 6iLF/4EQrNr̜fw k0}}hgsN\\cqa5,;K RuǏݻ/$w 1VU]_Z90Yt";;0)ioge3rqF,oܨ~9v =HljjH$tZ"0 &i tGGf)/ Iy',FTzMF؞{f˯g<k kiٕ SRh5UǵZ96Yt"!aWQ/sSC) 9sL2dYf8q5/Oh4Mnn^JJ ')))''(si{ttZ[[oHIdmm3~@/E+7lؠRetT CjV}#G>jW\Y~=֝jjj2zhMUqVD;عssrE"~2rd$+6nL73Wо*xeTTtPP]j:CaaD2!66.66nDiAAmO -\q.3Spᢀ)_NƗV=a1fe:o21qeH4===11,5yеZ:ϯWLLlh;v2A9nztbQQQEE9mV+F"D((kp-N#96 ;ڴB=F`4kepBk׾fM2pʎ}rb.d*ь8,a~E1һFF+k`9hرxU=ۍ, kzT2E:zWd>+kDv S Ɏ|tqW Z kXfiѮU2ڴ͌Vֺ {h \Q:ʱ hЊ; }}Oy 8rohЊ;;6c$IRmH':@QmbXvZq09W$X!^"٩a4" vȨ@'dVZYի6ńBB. ׯqd@ gDKRo_ʂVZلþ"0"trA yyyVZ7J!AصXhЊ= D1b7po @^ٵ~8ze}p.FmMIENDB`bookletimposer-0.2/README0000644000175000017500000000351311754703475014700 0ustar kjokjo00000000000000BookletImposer / pdfimposer Achieve some basic imposition on PDF documents What is it ? ============ Bookletimposer is an utility to achieve some basic imposition on PDF documents, especially designed to work on booklets. Bookletimposer is implemented as a commandline and GTK+ interface to pdfimposer, a reusable python module built on top of pyPdf. It was tested on GNU/Linux althought it may work on any systems with a Python interpreter. Bookletimposer and pdfimposer are both free software released under the GNU General Public License, either version 3 or (at your option) any later version. See COPYING for the full text of the license. Features ======== - transform linear documents to booklets - transform booklets to linear documents - reduce a document to put many on one sheet Development state ================= BookletImposer is under development, which means that for the moment, some things work, some others does not... Thanks to report bugs to if you find some! Furethermore, some funtionalities are still to be implemented. Dependencies ============ pdfimposer requires: - python (>= 2.6) - pyPdf (>= 1.13) BookletImposer also requires: - PyGObject - gtk+ (>= 3.0) - glib In addition, the build and installation process requires: - python-distutils-extra - pandoc Quick installation ================== Once the tarball downloaded and extracted: $ ./setup.py build Then as root: # ./setup.py install pdfimposer API documentation ============================ See generated epydoc documentation (available at ) BookletImposer usage ==================== BookletImposer can be launched from the Office section of the Application menu, or with te command: $ bookletimposer Help on command line options is available in the man page. bookletimposer-0.2/doc/0000755000175000017500000000000011754704533014557 5ustar kjokjo00000000000000bookletimposer-0.2/doc/bookletimposer.1.mdwn0000644000175000017500000000564711754704276020663 0ustar kjokjo00000000000000% BOOKLETIMPOSER(1) bookletimposer user manual % Kjö Hansi Glaz % 2012 NAME ==== **bookletimposer** - An utility to reorganize PDF pages SYNOPSIS ======== **bookletimposer** [*options*] [*input-file*] **bookletimposer** **-a** [*options*] *input-file* DESCRIPTION =========== bookletimposer is an utility to achieve some basic imposition on PDF documents, especially designed to work on booklets. It allows: - to transform linear documents to booklets; - to reduce a document to put many on one sheet (for tracts for example); - to transform booklets to linear documents. It is a free software released under the GNU General Public License, either version 3 or (at your option) any later version. OPTIONS ======= `--version` ----------- show program's version number and exit. `-h`, `--help` -------------- show an help message and exit. `-o` *OUTFILE*, `--output=`*OUTFILE* ------------------------------------ set output PDF file to *OUTFILE*. `-a`, `--no-gui` ---------------- automatic converstion (don't show the user interface). In that mode, the input file must be defined. `-i`, `--gui` ------------- show the user interface (default). `-b`, `--booklet` ----------------- produce a booklet out of a linear document (default). `-l`, `--linearize` ------------------- produce a linear document out of a booklet. `-n`, `--no-reorganisation` --------------------------- don't reorganize (will only scale and assemble pages). `-c`, `--copy-pages` -------------------- copy the same group of input pages on one output page. `-p` *PAGES_PER_SHEET*, `--pages-per-sheet=`*PAGES_PER_SHEET* ------------------------------------------------------------- number of pages per sheet, in the format HORIZONTALxVERTICAL, e.g. 2x1. `-f` *OUTPUT_FORMAT*, `--format=`*OUTPUT_FORMAT* ------------------------------------------------ output page format, e.g. A4 or A3R. `-k`, `--keep` -------------- do not overwrite output file if it exists. EXAMPLES ======== bookletimposer -------------- Displays the GTK+ user interface. bookletimposer --no-gui --booklet --pages-per-sheet=2x1 --output=out.pdf in.pdf ------------------------------------------------------------------------------- Converts in.pdf into a booklet with two pages per sheet an saves the result as out.pdf. bookletimposer --no-gui --linearise --pages-per-sheet=2x1 in.pdf ---------------------------------------------------------------- Converts the two-pages-per-sheet booklet in.pdf into a page-by-page PDF. As the output file name is not defined, it will default to in-conv.pdf. SEE ALSO ======== pdfshuffler(1) BookletImposer source code and documentation can be found on the web at KNOWN ISSUES ============ BookletImposer is under development, which means that for the moment, some things work, some others do not... Thanks to report bugs to if you find some! bookletimposer-0.2/setup.cfg0000644000175000017500000000010211717523300015612 0ustar kjokjo00000000000000[build] icons=False help=True [build_i18n] domain=bookletimposer bookletimposer-0.2/lib/0000755000175000017500000000000011754704533014560 5ustar kjokjo00000000000000bookletimposer-0.2/lib/pdfimposer.py0000644000175000017500000011323711754704213017304 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # pdfimposer - achieve some basic imposition on PDF documents # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # pdfimposer.py # # This python module enables to change PDF page layout. It is the backend # of BookletImposer, but is designed to be easily usable by from any python # script. # ######################################################################## """ Converts PDF documents between different page layouts. This module enables to: - convert linear (page by page) PDF documents to booklets; - revert booklets to linear documents; - reduce multiple input PDF pages and put them on one single output page. The `StreamConverter` class works on StreamIO, while the `FileConverter` class works on files. Some convenience functions are also provided. """ # XXX: File should be ASCII from abc import ABCMeta, abstractmethod import re import sys import os import types import pyPdf import pyPdf.generic import pyPdf.pdf # XXX: Fix these translatable strings try: _ except NameError: _ = lambda x: x __docformat__ = "restructuredtext" ######################################################################## # CONSTANTS class PageOrientation: """The page orientation constants""" PORTRAIT = False """The portrait orientation""" LANDSCAPE = True """The lanscape orientation""" ######################################################################## class PdfConvError(Exception): """ The base class for all exceptions raised by PdfImposer. The attribute "message" contains a message explaining the cause of the error. """ def __init__(self, message=None): Exception.__init__(self) self.message = message ######################################################################## class MismachingOrientationsError(PdfConvError): """ This exception is raised if the required layout is incompatible with the input page orientation. The attribute "message" contains the problematic layout. """ def __str__(self): return _("The layout %s is incompatible with the input page orientation") \ % self.message ######################################################################## class UnknownFormatError(PdfConvError): """ This exception is raised when the user tries to set an unknown page format. The attribute "message" contains the problematic format. """ def __str__(self): return _('The page format "%s" is unknown') % self.message ######################################################################## class UserInterruptError(PdfConvError): """ This exception is raised when the user interrupts the conversion. """ def __str__(self): return _('User interruption') % self.message ######################################################################## class AbstractConverter(object): """ The base class for all pdfimposer converter classes. It is an abstract class, with some abstract functions which should be overriden : - get_input_height - get_input_width - get_page_count - bookletize - linearize - reduce """ __metaclass__ = ABCMeta page_formats = { "A3":(841,1190), "A3":(842,1192), "A4":(595,841), "A4":(595,842), "A5":(420,595), } def __init__(self, layout='2x1', format='A4', copy_pages=False): """ Create an AbstractConverter instance. :Parameters: - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ self.layout = None self.output_format = None self.output_orientation = None self.set_layout(layout) self.set_output_format(format) self.set_copy_pages(copy_pages) def default_progress_callback(msg, prog): print "%s (%i%%)" % (msg, prog*100) self.set_progress_callback(default_progress_callback) # GETTERS AND SETTERS # =================== def set_output_height(self, height): """ Set the height of the output page. :Parameters: - `height` The height of the output page in defalut user space units. """ self.__output_height = int(height) def get_output_height(self): """ Get the height of the output page. :Returns: The height of the output page in defalut user space units. """ return self.__output_height def set_output_width(self, width): """ Set the width of the output page. - `width` The height of the output page in defalut user space units. """ self.__output_width = int(width) def get_output_width(self): """ Get the width of the output page. :Returns: The width of the output page in defalut user space units. """ return self.__output_width def set_pages_in_width(self, num): """ Set the number of input pages to put in the width on one output page. :Parameters: - `num` An integer representing the number of pages in width. """ self.__pages_in_width = int(num) def get_pages_in_width(self): """ Get the number of input pages to put in the width on one output page. :Returns: An integer representing the number of pages in width. """ return self.__pages_in_width def set_pages_in_height(self, num): """ Set the number of input pages to put in the height on one output page. :Parameters: - `num` An integer representing the number of pages in height. """ self.__pages_in_height = int(num) def get_pages_in_height(self): """ Get the number of input pages to put in the height on one output page. :Returns: An integer representing the number of pages in height. """ return self.__pages_in_height def set_copy_pages(self, copy_pages): """ Set wether the same group of input pages shoud be copied to fill the corresponding output page or not. :Parameters: - `copy_pages` True to get copies of the same group of input page on one output page. False to get diffrent groups of input pages on one output page. """ self.__copy_pages = bool(copy_pages) def get_copy_pages(self): """ Get wether the same group of input pages will be copied to fill the corresponding output page or not. :Returns: True if copies of the same group of input page will get copied on one output page. False if diffrent groups of input pages will go on one output page. """ return self.__copy_pages def set_progress_callback(self, progress_callback): """ Register a progress callback function. Register a callback function that will be called to inform on the progress of the conversion. :Parameters: - `progress_callback` The callback function which is called to return the conversion progress. Its signature must be : a string for the progress message; a number in the range [0, 1] for the progress. """ assert(type(progress_callback) is types.FunctionType) self.__progress_callback = progress_callback def get_progress_callback(self): """ Get the progress callback function. Get the callback function that will be called to inform on the progress of the conversion. :Returns: The callback function which is called to return the conversion progress. """ return self.__progress_callback # SOME GETTERS THAT CALCULATE THE VALUE THEY RETURN FROM OTHER VALUES # =================================================================== def get_input_size(self): """ Return the page size of the input document. :Returns: A tuple (width, height) representing the page size of the input document expressed in default user space units. """ return (self.get_input_width(), self.get_input_height()) @abstractmethod def get_input_height(self): """ Return the page height of the input document. :Returns: The page height of the input document expressed in default user space units. """ raise NotImplementedError("get_input_height must be implemented in a subclass.") @abstractmethod def get_input_width(self): """ Return the page width of the input document. :Returns: The page width of the input document expressed in default user space units. """ raise NotImplementedError("get_input_width must be implemented in a subclass.") def get_input_orientation(self): """ Return the page orientation of the input document. :Returns: A constant from PageOrientation, or None (if square paper). """ if self.get_input_height() > self.get_input_width(): return PageOrientation.PORTRAIT elif self.get_input_height() < self.get_input_width(): return PageOrientation.LANDSCAPE else: #XXX: is square return None def set_layout(self, layout): """ Set the layout of input pages on one output page. :Parameters: - `layout` A string of the form WxH, where W is the number of input pages to put on the width of the output page and H is the number of input pages to put in the height of an output page. """ pages_in_width, pages_in_height = layout.split('x') self.set_pages_in_width(int(pages_in_width)) self.set_pages_in_height(int(pages_in_height)) def get_layout(self): """ Return the layout of input pages on one output page. :Returns: A string of the form WxH, where W is the number of input pages to put on the width of the output page and H is the number of input pages to put in the height of an output page. """ return str(self.get_pages_in_width()) + 'x' + str(self.get_pages_in_height()) def get_pages_in_sheet(self): """ Calculate the number of input page that will be put on one output page. :Returns: An integer representing the number of input pages on one output page. """ return self.get_pages_in_width() * self.get_pages_in_height() def set_output_format(self, format): """ Set the format of the output paper. :Parameters: - `format` A string representing name ot the the desired paper format, among the keys of page_formats (e.g. A3, A4, A5). :Raises UnknonwFormatError: if the given paper format is not recognized. """ try: width, height = AbstractConverter.page_formats[format] self.set_output_height(height) self.set_output_width(width) except KeyError: raise UnknownFormatError(format) def get_output_format(self): """ Return the format of the output paper. :Returns: A string representing the name of the paper format (e.g. A3, A4, A5). """ for output_format in AbstractConverter.page_formats.keys(): if AbstractConverter.page_formats[output_format] == \ (self.get_output_width, self.get_output_height): return output_format def get_input_format(self): """ Return the format of the input paper :Returns: A string representing the name of the paper format (e.g. A3, A4, A5). """ width, height = self.get_input_size() if self.get_input_orientation() == PageOrientation.LANDSCAPE: size = height, width else: size = width, height for k in self.page_formats.keys(): if self.page_formats[k] == size: return k @abstractmethod def get_page_count(self): """ Return the number of pages of the input document. :Returns: The number of pages of the input document. """ raise NotImplementedError("get_page_count must be implemented in a subclass.") def get_reduction_factor(self): """ Calculate the reduction factor. :Returns: The reduction factor to be applied to an input page to obtain its size on the output page. """ return float(self.get_output_width()) / \ (self.get_pages_in_width() * self.get_input_width()) def get_increasing_factor(self): """ Calculate the increasing factor. :Returns: The increasing factor to be applied to an input page to obtain its size on the output page. """ return float(self.get_pages_in_width() * self.get_output_width()) / \ self.get_input_width() def _set_output_orientation(self, output_orientation): """ Set the orientation of the output paper. WARNING: in the current implementation, the orientation of the output paper may be automatically adjusted, even if ti was set manually. :Parameters: - `output_orientation` A constant from PageOrientation, or None (if square paper). """ output_orientation = bool(output_orientation) w = self.get_output_width() h = self.get_output_height() if (output_orientation == PageOrientation.PORTRAIT and w > h) or \ (output_orientation == PageOrientation.LANDSCAPE and h > w): self.set_output_height(w) self.set_output_width(h) def _get_output_orientation(self): """ Return the orientation of the output paper. WARNING: in the current implementation, the orientation of the output paper may be automatically adjusted, even if it was set manually. :Returns: A constant among from PageOrientation, or None (if square paper). """ if self.get_output_height() > self.get_output_width(): return PageOrientation.PORTRAIT elif self.get_output_height() < self.get_output_width(): return PageOrientation.LANDSCAPE else: return None # CONVERSION FUNCTIONS # ==================== @abstractmethod def bookletize(self): """ Convert a linear document to a booklet. Convert a linear document to a booklet, arranging the pages as required. """ raise NotImplementedError("bookletize must be implemented in a subclass.") @abstractmethod def linearize(self): """ Convert a booklet to a linear document. Convert a booklet to a linear document, arranging the pages as required. """ raise NotImplementedError("linearize must be implemented in a subclass.") @abstractmethod def reduce(self): """ Put multiple input pages on one output page. """ raise NotImplementedError("reduce must be implemented in a subclass.") ######################################################################## class StreamConverter(AbstractConverter): """ This class performs conversions on file-like objects (e.g. a StreamIO). """ def __init__(self, input_stream, output_stream, layout='2x1', format='A4', copy_pages=False): """ Create a StreamConverter. :Parameters: - `input_stream` The file-like object from which tne input PDF document should be read. - `output_stream` The file-like object to which tne output PDF document should be written. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ AbstractConverter.__init__(self, layout, format, copy_pages) self._output_stream = output_stream self._input_stream = input_stream self._inpdf = pyPdf.PdfFileReader(input_stream) def get_input_height(self): page = self._inpdf.getPage(0) height = page.mediaBox.getHeight() return int(height) def get_input_width(self): page = self._inpdf.getPage(0) width = page.mediaBox.getWidth() return int(width) def get_page_count(self): return self._inpdf.getNumPages() def __fix_page_orientation(self, cmp): """ Adapt the output page orientation. :Parameters: - `cmp` A comparator function. Takes: number of pages on one direction (int), number of pages on the other direction (int). Must return: the boolean result of the comparaison. :Raises MismachingOrientationsError: if the required layout is incompatible with the input page orientation. """ if cmp(self.get_pages_in_width(), self.get_pages_in_height()): if self.get_input_orientation() == PageOrientation.PORTRAIT: if self._get_output_orientation() == PageOrientation.PORTRAIT: self._set_output_orientation(PageOrientation.LANDSCAPE) else: raise MismachingOrientationsError(self.get_layout()) elif cmp(self.get_pages_in_height(), self.get_pages_in_width()): if self.get_input_orientation() == PageOrientation.LANDSCAPE: if self._get_output_orientation() == PageOrientation.LANDSCAPE: self._set_output_orientation(PageOrientation.PORTRAIT) else: raise MismachingOrientationsError(self.get_layout()) else: if self.get_input_orientation() == PageOrientation.LANDSCAPE: if self._get_output_orientation() == PageOrientation.PORTRAIT: self._set_output_orientation(PageOrientation.LANDSCAPE) else: if self._get_output_orientation() == PageOrientation.LANDSCAPE: self._set_output_orientation(PageOrientation.PORTRAIT) def __fix_page_orientation_for_booklet(self): """ Adapt the output page orientation to impose """ def __is_two_times(op1, op2): if op1 == 2 * op2: return True else: return False self.__fix_page_orientation(__is_two_times) def __fix_page_orientation_for_linearize(self): """ Adapt the output page orientation to linearize """ def __is_half(op1, op2): if op2 == 2 * op1: return True else: return False self.__fix_page_orientation(__is_half) def __get_sequence_for_booklet(self): """ Calculates the page sequence to impose a booklet. :Returns: A list of page numbers representing sequence of pages to impose a booklet. The list might contain None where blank pages should be added. """ n_pages = self.get_page_count() pages = range(0, n_pages) # Check for missing pages if (n_pages % 4) == 0: n_missing_pages = 0 else: n_missing_pages = 4 - (n_pages % 4) # XXX: print a warning if input page number not diviable by 4? # Add reference to the missing empty pages to the pages sequence for missing_page in range(0, n_missing_pages): pages.append(None) def append_and_copy(list, pages): """ Append pages to the list and copy them if needed """ if self.get_copy_pages(): for i in range(self.get_pages_in_sheet() / 2): list.extend(pages) else: list.extend(pages) # Arranges the pages in booklet order sequence = [] while pages: append_and_copy(sequence, [pages.pop(), pages.pop(0)]) append_and_copy(sequence, [pages.pop(0), pages.pop()]) return sequence def __get_sequence_for_linearize(self, booklet=True): """ Calculates the page sequence to lineraize a booklet. :Returns: A list of page numbers representing sequence of pages to be extracted to linearize a booklet. """ # XXX: is booklet argument useful? def append_and_remove_copies(list, pages): sequence.extend(pages) if self.get_copy_pages(): for copy in range(self.get_pages_in_sheet() - len(pages)): sequence.append(None) if booklet: sequence = [] try : for i in range(0, self.get_page_count() * self.get_pages_in_sheet(), 4): append_and_remove_copies(sequence, [i / 2, i / 2]) append_and_remove_copies(sequence, [i / 2 + 1, i / 2 + 2]) except IndexError : # XXX: Print a warning pass else: sequence = range(0, self.get_page_count() * self.get_pages_in_sheet()) return sequence def __get_sequence_for_reduce(self): """ Calculates the page sequence to linearly impose reduced pages. :Returns: A list of page numbers representing sequence of pages to impose reduced pages. The list might contain None where blank pages should be added. """ if self.get_copy_pages(): sequence = [] for page in range(self.get_page_count()): for copy in range(self.get_pages_in_sheet()): sequence.append(page) else: sequence = range(self.get_page_count()) if len(sequence) % self.get_pages_in_sheet() != 0: for missing_page in range(self.get_pages_in_sheet() - (len(sequence) % self.get_pages_in_sheet())): sequence.append(None) return sequence def __write_output_stream(self, outpdf): """ Writes output to the stream. :Parameters: - `outpdf` the object to write to the stream. This object must have a write() method. """ self.get_progress_callback()(_("writing converted file"), 1) outpdf.write(self._output_stream) self.get_progress_callback()(_("done"), 1) def __do_reduce(self, sequence): """ Do actual imposition job. :Parameters: - `sequence` a list of page numbers repersenting the sequence of pages to impose. None means blank page. """ # XXX: Translated progress messages self.__fix_page_orientation_for_booklet() outpdf = pyPdf.PdfFileWriter() current_page = 0 while current_page < len(sequence): self.get_progress_callback()( _("creating page %i") % ((current_page + self.get_pages_in_sheet()) / self.get_pages_in_sheet()), float(current_page) / len(sequence) ) page = outpdf.addBlankPage(self.get_output_width(), self.get_output_height()) for vert_pos in range(0, self.get_pages_in_height()): for horiz_pos in range(0, self.get_pages_in_width()): if current_page < len(sequence) and sequence[current_page] is not None: page.mergeScaledTranslatedPage( self._inpdf.getPage(sequence[current_page]), self.get_reduction_factor(), horiz_pos*self.get_output_width() / \ self.get_pages_in_width(), self.get_output_height() - ( (vert_pos + 1) * self.get_output_height() / \ self.get_pages_in_height()) ) current_page += 1 page.compressContentStreams() self.__write_output_stream(outpdf) def bookletize(self): self.__do_reduce(self.__get_sequence_for_booklet()) def reduce(self): self.__do_reduce(self.__get_sequence_for_reduce()) def linearize(self, booklet=True): # XXX: Translated progress messages # XXX: Wrong zoom factor e.g. when layout is 2x1 self.__fix_page_orientation_for_linearize() sequence = self.__get_sequence_for_linearize() outpdf = pyPdf.PdfFileWriter() output_page = 0 for input_page in range(0, self.get_page_count()): for vert_pos in range(0, self.get_pages_in_height()): for horiz_pos in range(0, self.get_pages_in_width()): if sequence[output_page] is not None: self.get_progress_callback()( _("extracting page %i") % (output_page + 1), float(output_page) / len(sequence)) page = outpdf.insertBlankPage(self.get_output_width(), self.get_output_height(), sequence[output_page]) page.mergeScaledTranslatedPage( self._inpdf.getPage(input_page), self.get_increasing_factor(), - horiz_pos * self.get_output_width(), (vert_pos - self.get_pages_in_height() + 1) * \ self.get_output_height() ) page.compressContentStreams() output_page += 1 self.__write_output_stream(outpdf) ######################################################################## class FileConverter(StreamConverter): """ This class performs conversions on true files. """ def __init__(self, infile_name, outfile_name=None, layout='2x1', format='A4', copy_pages=False, overwrite_outfile_callback=None): """ Create a FileConverter. :Parameters: - `infile_name` The name to the input PDF file. - `outfile_name` The name of the file where the output PDF should de written. If ommited, defaults to the name of the input PDF postponded by '-conv'. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). - `overwrite_outfile_callback` A callback function which is called if outfile_name already exists when trying to open it. Its signature must be : take a string for the outfile_name as an argument; return False not to overwrite the file. If ommited, existing file would be overwritten without confirmation. """ # sets [input, output]_stream to None so we can test their presence # in __del__ self._input_stream = None self._output_stream = None # outfile_name is set if provided if outfile_name: self.__set_outfile_name(outfile_name) else: self.__set_outfile_name(None) # Then infile_nameis set, so if outfile_name was not provided we # can create it from infile_name self.__set_infile_name(infile_name) # Setup callback to ask for confirmation before overwriting outfile if overwrite_outfile_callback: assert(type(overwrite_outfile_callback) is types.FunctionType) else: overwrite_outfile_callback = lambda filename: True # Now initialize a streamConverter self._input_stream = open(self.get_infile_name(), 'rb') outfile_name = self.get_outfile_name() if (os.path.exists(outfile_name) and not overwrite_outfile_callback(os.path.abspath(outfile_name))): raise UserInterruptError() self._output_stream = open(outfile_name, 'wb') StreamConverter.__init__(self, self._input_stream, self._output_stream, layout, format, copy_pages) def __del__(self): if self._input_stream: try: self._input_stream.close() except IOError: # XXX: Do something better pass if self._output_stream: try: self._output_stream.close() except IOError: # XXX: Do something better pass # GETTERS AND SETTERS SECTION # =========================== def __set_infile_name(self, name): """ Sets the name of the input PDF file. Also set the name of output PDF file if not already set. :Parameters: - `name` the name of the input PDF file. """ self.__infile_name = name if not self.__outfile_name: result = re.search("(.+)\.\w*$", name) if result: self.__outfile_name = result.group(1) + '-conv.pdf' else: self.__outfile_name = name + '-conv.pdf' def get_infile_name(self): """ Get the name of the input PDF file. :Returns: The name of the input PDF file. """ return self.__infile_name def __set_outfile_name(self, name): """ Sets the name of the output PDF file. :Parameters: - `name` the name of the output PDF file. """ self.__outfile_name = name def get_outfile_name(self): """ Get the name of the output PDF file. :Returns: The name of the output PDF file. """ return self.__outfile_name # Convenience functions # ===================== def bookletize_on_stream(input_stream, output_stream, layout='2x1', format='A4', copy_pages=False): """ Convert a linear document to a booklet. Convert a linear document to a booklet, arranging the pages as required. This is a convenience function around StreamConverter :Parameters: - `input_stream` The file-like object from which tne input PDF document should be read. - `output_stream` The file-like object to which tne output PDF document should be written. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ StreamConverter(layout, format, copy_pages, input_stream, output_stream()).bookletize() def bookletize_on_file(input_file, output_file=None, layout='2x1', format='A4', copy_pages=False): """ Convert a linear PDF file to a booklet. Convert a linear PDF file to a booklet, arranging the pages as required. This is a convenience function around FileConverter :Parameters: - `input_file` The name to the input PDF file. - `output_file` The name of the file where the output PDF should de written. If ommited, defaults to the name of the input PDF postponded by '-conv'. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ FileConverter(input_file, output_file, layout, format, copy_pages).bookletize() def linearize_on_stream(input_stream, output_stream, layout='2x1', format='A4', copy_pages=False): """ Convert a booklet to a linear document. Convert a booklet to a linear document, arranging the pages as required. This is a convenience function around StreamConverter :Parameters: - `input_stream` The file-like object from which tne input PDF document should be read. - `output_stream` The file-like object to which tne output PDF document should be written. - `layout` The layout of output pages on one input page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ StreamConverter(input_stream, output_stream, layout, format, copy_pages).linearize() def linearize_on_file(input_file, output_file=None, layout='2x1', format='A4', copy_pages=False): """ Convert a booklet to a linear PDF file. Convert a booklet to a linear PDF file, arranging the pages as required. This is a convenience function around FileConverter :Parameters: - `input_file` The name to the input PDF file. - `output_file` The name of the file where the output PDF should de written. If ommited, defaults to the name of the input PDF postponded by '-conv'. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ FileConverter(input_file, output_file, layout, format, copy_pages).linearize() def reduce_on_stream(input_stream, output_stream, layout='2x1', format='A4', copy_pages=False): """ Put multiple input pages on one output page. This is a convenience function around StreamConverter :Parameters: - `input_stream` The file-like object from which tne input PDF document should be read. - `output_stream` The file-like object to which tne output PDF document should be written. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ StreamConverter(input_stream, output_stream, layout, format, copy_pages).reduce() def reduce_on_file(input_file, output_file=None, layout='2x1', format='A4', copy_pages=False): """ Put multiple input pages on one output page. This is a convenience function around FileConverter :Parameters: - `input_file` The name to the input PDF file. - `output_file` The name of the file where the output PDF should de written. If ommited, defaults to the name of the input PDF postponded by '-conv'. - `layout` The layout of input pages on one output page (see set_layout). - `format` The format of the output paper (see set_output_format). - `copy_pages` Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ FileConverter(input_file, output_file, layout, format, copy_pages).reduce() bookletimposer-0.2/lib/bookletimposer/0000755000175000017500000000000011754704533017616 5ustar kjokjo00000000000000bookletimposer-0.2/lib/bookletimposer/gui.py0000644000175000017500000003520711754516617020767 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # PdfImposer - Utility to convert PDF files between diffrents page layouts # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # gui.py # # This file contains the GTK+ graphic utility. # ######################################################################## import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib from gi.repository import GObject GObject.threads_init() from gi.repository import Gio import os.path import threading import traceback import pdfimposer # We need its exceptions import backend import pdfimposer import config from config import debug class UserInterrupt(backend.BookletImposerError): """Exception raised when the user interrupted the conversion """ # XXX: this is probably not the right way to do... class BookletImposerUI(object): """BookletImposer graphical user interface """ def __init__(self, preferences=None): """ """ if preferences: self.__preferences = preferences else: self.__preferences = backend.ConverterPreferences() self.__create_gui() if preferences: self.__apply_preferences() self.__main_window.show() def __create_gui(self): Gtk.IconTheme.get_default().append_search_path(config.get_datadir()) builder = Gtk.Builder() builder.set_translation_domain("bookletimposer") builder.add_from_file(os.path.join(config.get_datadir(), "bookletimposer.ui")) builder.connect_signals(self) self.__main_window = builder.get_object("main_window") self.__preferences_table = builder.get_object("preferences_table") self.__input_file_chooser_button = \ builder.get_object("input_file_chooser_button") self.__bookeltize_radiobutton = builder.get_object("bookletize_radiobutton") self.__linearize_radiobutton = builder.get_object("linearize_radiobutton") self.__reduce_radiobutton = builder.get_object("reduce_radiobutton") self.__copy_pages_radiobutton = builder.get_object("copy_pages_radiobutton") self.__layout_combobox = builder.get_object("layout_combobox") self.__paper_format_combobox = \ builder.get_object("output_paper_format_combobox") self.__output_file_chooser_button = self.__create_output_file_chooser_button(builder) self.__progressbar_conversion = builder.get_object("conversion_progressbar") self.__about_button = builder.get_object("about_button") self.__help_button = builder.get_object("help_button") self.__apply_button = builder.get_object("apply_button") self.__stop_button = builder.get_object("stop_button") self.__about_dialog = builder.get_object("about_dialog") self.__fill_paper_formats() self.__fill_layouts() self.__add_keybindings() def __add_keybindings(self): accelgroup = Gtk.AccelGroup() accelgroup.connect(Gdk.KEY_Escape, 0, Gtk.AccelFlags.VISIBLE, lambda group, accelerable, key, mod: self.close_application()) accelgroup.connect(Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE, lambda group, accelerable, key, mod: self.close_application()) self.__main_window.add_accel_group(accelgroup) def __create_output_file_chooser_button(self, builder): # Emulate a FileChooserButton for saving output_file_chooser_button = \ builder.get_object("output_file_chooser_button") output_file_chooser_button.__filename = None def output_file_chooser_button_set_filename(filename): output_file_chooser_button.__filename = filename output_file_chooser_file_image = \ builder.get_object("output_file_chooser_file_image") output_file_chooser_label = \ builder.get_object("output_file_chooser_label") output_file_chooser_label.set_text(os.path.basename(filename)) output_file_chooser_file_image.set_visible(True) output_file_chooser_button.set_filename = \ output_file_chooser_button_set_filename def output_file_chooser_button_get_filename(): return self.__output_file_chooser_button.__filename output_file_chooser_button.get_filename = \ output_file_chooser_button_get_filename return output_file_chooser_button @staticmethod def set_liststore_for_combobox(combobox): liststore = Gtk.ListStore(GObject.TYPE_STRING) combobox.set_model(liststore) cell = Gtk.CellRendererText() combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0) return liststore def __fill_paper_formats(self): liststore = self.set_liststore_for_combobox( self.__paper_format_combobox) formats = pdfimposer.AbstractConverter.page_formats.keys() formats.sort() for format in formats: liststore.append([format]) self.__paper_format_combobox.set_active(1) def __fill_layouts(self): liststore = self.set_liststore_for_combobox( self.__layout_combobox) for layout in ["2x1", "2x2", "2x4", "4x4"]: liststore.append([layout]) self.__layout_combobox.set_active(0) @staticmethod def combobox_select_row(widget, row_value): def func(model, path, iter, widget): if model.get_value(iter, 0) == row_value: widget.set_active_iter(iter) widget.get_model().foreach(func, widget) def __apply_preferences(self): preferences = self.__preferences if preferences.infile_name: self.__input_file_chooser_button.set_filename(preferences.infile_name) self.__apply_button.set_sensitive(True) if preferences.conversion_type: if preferences.conversion_type == backend.ConversionType.BOOKLETIZE: self.__bookeltize_radiobutton.set_active(True) if preferences.conversion_type == backend.ConversionType.LINEARIZE: self.__linearize_radiobutton.set_active(True) if preferences.conversion_type == backend.ConversionType.REDUCE: self.__reduce_radiobutton.set_active(True) if preferences.copy_pages: self.__copy_pages_radiobutton.set_active(preferences.copy_pages) if preferences.layout: self.combobox_select_row(self.__layout_combobox, preferences.layout) if preferences.paper_format: self.combobox_select_row(self.__paper_format_combobox, preferences.paper_format) if preferences.outfile_name: self.__output_file_chooser_button.set_filename(preferences.outfile_name) # CALLBACKS def cb_close_main_window(self, widget, event, data=None): self.close_application() def cb_dialog_close(self, dialog, data=None): dialog.hide() def cb_infile_set(self, widget, data=None): self.__preferences.infile_name = widget.get_filename() self.__apply_preferences() def cb_bookletize_toggled(self, widget, data=None): if widget.get_active(): self.__preferences.conversion_type = backend.ConversionType.BOOKLETIZE def cb_linearize_toggled(self, widget, data=None): if widget.get_active(): self.__preferences.conversion_type = backend.ConversionType.LINEARIZE def cb_reduce_toggled(self, widget, data=None): if widget.get_active(): self.__preferences.conversion_type = backend.ConversionType.REDUCE def cb_copy_pages_toggled(self, widget, data=None): self.__preferences.copy_pages = widget.get_active() def cb_layout_changed(self, widget, data=None): self.__preferences.layout = widget.get_model().get_value( widget.get_active_iter(), 0) def cb_paper_format_changed(self, widget, data=None): self.__preferences.paper_format = widget.get_model().get_value( widget.get_active_iter(), 0) def cb_outfile_clicked(self, widget, data=None): fcdialog = Gtk.FileChooserDialog( title=_("Choose file to save"), parent=self.__main_window, action=Gtk.FileChooserAction.SAVE, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK)) if widget.get_filename(): fcdialog.set_filename(widget.get_filename()) if fcdialog.run() == Gtk.ResponseType.OK: if fcdialog.get_filename(): widget.set_filename(fcdialog.get_filename()) self.__preferences.outfile_name = fcdialog.get_filename() fcdialog.destroy() def cb_about_button(self, widget, data=None): self.show_about_dialog() def cb_close_button(self, widget, data=None): self.close_application() def cb_help_button(self, widget, data=None): uri = "ghelp:bookletimposer" try: Gtk.show_uri(screen = None, uri = uri, timestamp = Gtk.get_current_event_time()) except Gio.Error, error: dialog = Gtk.MessageDialog(parent=self.__main_window, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE, message_format=_("Unable to display help: %s") % str(error)) dialog.connect("response", lambda widget, data=None: widget.destroy()) dialog.run() def cb_apply_button(self, widget, data=None): self.run_conversion() pass def cb_progress_stop(self, widget, data=None): self.__stop.set() self.__progressbar_conversion.set_text(_("Cancel triggered, please wait...")) # ACTIONS def close_application(self): Gtk.main_quit() def show_about_dialog(self): self.__about_dialog.show() def run_conversion(self): def exception_dialog(exception): dialog = Gtk.MessageDialog(parent=self.__main_window, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE, message_format=_("Conversion failed")) dialog.format_secondary_text(str(exception)) dialog.run() dialog.destroy() stop_conversion_mode() def start_conversion_mode(): self.__preferences_table.set_sensitive(False) self.__progressbar_conversion.set_visible(True) self.__progressbar_conversion.set_fraction(0) self.__progressbar_conversion.set_text("") self.__stop_button.set_visible(True) self.__stop_button.show() self.__apply_button.set_visible(False) def stop_conversion_mode(): self.__preferences_table.set_sensitive(True) self.__progressbar_conversion.set_visible(False) self.__apply_button.set_visible(True) self.__stop_button.set_visible(False) def cb_overwrite_outfile(filename): dialog = Gtk.MessageDialog(parent=self.__main_window, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO, message_format=_("A file named %s already exist.") % filename) dialog.format_secondary_text(_("Do you want to replace it?")) resp = dialog.run() dialog.destroy() if resp == Gtk.ResponseType.YES: return True else: return False def cb_update_progress(message, progress): # there we are inside the work of the converter, # so we can to stop it if the user required to cancel # the operation. To achieve that we raise an exception. # XXX: that's not elegant at all if self.__stop.is_set(): self.__progressbar_conversion.set_text(_("Conversion cancelled")) raise UserInterrupt() GObject.idle_add(idle_cb_update_progress, message, progress) def idle_cb_update_progress(message, progress): self.__progressbar_conversion.set_fraction(progress) self.__progressbar_conversion.set_text(message) return False def idle_cb_process_exception(exception): exception_dialog(exception) return False def idle_cb_finish_callback(): stop_conversion_mode() return False def worker(): try: converter.run() except UserInterrupt: GObject.idle_add(idle_cb_finish_callback) except Exception, e: GObject.idle_add(idle_cb_process_exception, e) print traceback.format_exc() raise GObject.idle_add(idle_cb_finish_callback) start_conversion_mode() try: converter = self.__preferences.create_converter(cb_overwrite_outfile) except pdfimposer.UserInterruptError: stop_conversion_mode() return except Exception, e: exception_dialog(e) raise converter.set_progress_callback(cb_update_progress) self.__stop = threading.Event() converter_thread = threading.Thread(target=worker) converter_thread.start() if __name__ == "__main__": ui = BookletImposerUI() Gtk.main() bookletimposer-0.2/lib/bookletimposer/backend.py0000644000175000017500000002134311754703631021560 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # BookletImposer - Utility to achieve some basic imposition on PDF documents # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # backend.py # # This file contains backend that should not be part of the pdfimposer # python module. # ######################################################################## import pdfimposer import os.path import re class BookletImposerError(pdfimposer.PdfConvError): """The base class for all exceptions raised by BookletImposer. The attribute "message" contains a message explaining the cause of the error. """ class MissingInputFileError(BookletImposerError): """Excpetion raised when trying to create a converter withot an input file. An input file is required to create a converter." """ class ConversionType: """The conversion type constants""" BOOKLETIZE = 1 """The conversion from a linear document to a booklet""" LINEARIZE = 2 """The conversion from a booklet to a linear document""" REDUCE = 3 """The conversion from multiple input pages to one output page""" class ConverterPreferences(object): def __init__(self): self._infile_name = None self._conversion_type = None self.copy_pages = None self.layout = None self.paper_format = None self.paper_orientation = None self.outfile_name = None self.__outfile_name_changed = False @property def infile_name(self): return self._infile_name @infile_name.setter def infile_name(self, value): assert value == None or os.path.isfile(value) self._infile_name = value # XXX: duplicate code with pfdimposer.FileConverter.__set_infile_name # but the least one is called only on FileConverer instanciation # and we need the proposal before to display it in the UI if not self.__outfile_name_changed: result = re.search("(.+)\.\w*$", value) if result: self._outfile_name = result.group(1) + '-conv.pdf' else: self._outfile_name = value + '-conv.pdf' @property def conversion_type(self): return self._conversion_type @conversion_type.setter def conversion_type(self, value): assert value == None or \ value == ConversionType.BOOKLETIZE or \ value == ConversionType.LINEARIZE or \ value == ConversionType.REDUCE self._conversion_type = value @property def copy_pages(self): return self._copy_pages @copy_pages.setter def copy_pages(self, value): self._copy_pages = bool(value) @property def layout(self): return self._layout @layout.setter def layout(self, value): # XXX : verify value self._layout = value @property def paper_format(self): return self._paper_format @paper_format.setter def paper_format(self, value): # XXX : verify value self._paper_format = value @property def paper_orientation(self): return self._paper_orientation @paper_orientation.setter def paper_orientation(self, value): # XXX : verify value self._paper_orientation = value @property def outfile_name(self): return self._outfile_name @outfile_name.setter def outfile_name(self, value): assert value == None or \ not os.path.dirname(value) or \ os.path.exists(os.path.dirname(value)) self.__outfile_name_changed = True self._outfile_name = value def __str__(self): string = "ConverterPreferences object:\n" if self._infile_name: string += " infile_name: %s\n" % self._infile_name if self._infile_name: string += " outfile_name: %s\n" % self._outfile_name if self._conversion_type: string += " conversion_type: %s\n" % self._conversion_type if self._layout: string += " layout: %s\n" % self._layout if self._paper_format: string += " paper_format: %s\n" % self._paper_format if self._paper_orientation: string += " paper_orientation: %s\n" % self._paper_orientation if self._copy_pages: string += " copy_pages: %s\n" % self._copy_pages return string def create_converter(self, overwrite_outfile_callback=None): if not self._infile_name: raise MissingInputFileError return None elif self._outfile_name: converter = TypedFileConverter(self._infile_name, self._outfile_name, overwrite_outfile_callback=overwrite_outfile_callback) else: converter = TypedFileConverter(self._infile_name, overwrite_outfile_callback=overwrite_outfile_callback) if self._conversion_type: converter.set_conversion_type(self._conversion_type) if self._layout: converter.set_layout(self._layout) if self._paper_format: converter.set_output_format(self._paper_format) if self._paper_orientation: converter._set_output_orientation(self._paper_orientation) if self._copy_pages: converter.set_copy_pages(self._copy_pages) return converter class TypedFileConverter(pdfimposer.FileConverter): """A FileConverter that stores the conversion type. """ def __init__(self, infile_name=None, outfile_name=None, conversion_type=ConversionType.BOOKLETIZE, layout='2x1', format='A4', copy_pages=False, overwrite_outfile_callback=None): """Create a TypedFileConverter. :Parameters: - `infile_name`: The name to the input PDF file. - `outfile_name`: The name of the file where the output PDF should de written. If ommited, defaults to the name of the input PDF postponded by '-conv'. - `conversion_type`: The type of the conversion that will be performed when caling run() (see set_converston_type). - `layout`: The layout of input pages on one output page (see set_layout). - `format`: The format of the output paper (see set_output_format). - `copy_pages`: Wether the same group of input pages shoud be copied to fill the corresponding output page or not (see set_copy_pages). """ pdfimposer.FileConverter.__init__(self, infile_name, outfile_name, layout, format, copy_pages, overwrite_outfile_callback) self._conversion_type = conversion_type # CONVERSION FUNCTIONS # ==================== def run(self): """Perform the actual conversion. This method launches the actual conversion, using the parameters set before. """ if self.get_conversion_type() == ConversionType.BOOKLETIZE: self.bookletize() elif self.get_conversion_type() == ConversionType.LINEARIZE: self.linearize() elif self.get_conversion_type() == ConversionType.REDUCE: self.reduce() # GETTERS AND SETTERS SECTION # =========================== def set_conversion_type(self, type): """Set conversion that will be performed when caling run(). :Parameters: - `type`: A constant from the ConversionType class. """ assert(type == ConversionType.BOOKLETIZE or \ type == ConversionType.LINEARIZE or \ type == ConversionType.REDUCE) self._conversion_type = type def get_conversion_type(self): """ Get conversion that will be performed when caling run(). :Returns: A constant from ConversionType class. """ return self._conversion_type bookletimposer-0.2/lib/bookletimposer/__init__.py0000644000175000017500000000266711717523300021730 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # PdfImposer - Utility to convert PDF files between diffrents page layouts # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # __init__.py # # This file contains bookletimposer package initialisation code. # ######################################################################## import gettext import locale import config locale.setlocale(locale.LC_ALL, '') locale.bindtextdomain("bookletimposer", config.get_localedir()) gettext.install("bookletimposer", localedir=config.get_localedir(), unicode=True) bookletimposer-0.2/lib/bookletimposer/config.py0000644000175000017500000000374411753601105021433 0ustar kjokjo00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- ######################################################################## # # BookletImposer - Utility to achieve some basic imposition on PDF documents # Copyright (C) 2008-2012 Kjö Hansi Glaz # # 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 . # ######################################################################## ######################################################################## # # config.py # # This file contains the configuration variables defined at install time # which will be used somewhere in the program. # ######################################################################## import gettext import locale import os.path def debug(msg): if __debug__: print msg def get_sharedir(): if os.path.exists(os.path.join("/", "usr", "local", "share", "bookletimposer")): return os.path.join("/", "usr", "local", "share") elif os.path.exists(os.path.join("/", "usr", "share", "bookletimposer")): return os.path.join("/", "usr", "share") else: return "" def get_datadir(): if __debug__ and os.path.exists("data"): return "data" else: return os.path.join(get_sharedir(), "bookletimposer") def get_helpdir(): return os.path.join(get_sharedir(), "gnome", "help") def get_localedir(): return os.path.join(get_sharedir(), "locale") bookletimposer-0.2/data/0000755000175000017500000000000011754704533014723 5ustar kjokjo00000000000000bookletimposer-0.2/data/linearise.png0000644000175000017500000002166711753601105017406 0ustar kjokjo00000000000000PNG  IHDRnh9{sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxYǙYG_=   EAD.ͰlҮ iw~˻RhQZ:aJYPVdicMmh%.x !P90GtWU!Ȫib1DMWefeeU~ߗYBJɆlȰu! * lzCJ݀)Bq5YCV^{??]vԄ[pܨRˀ+\v~'bEZz*;pZAJtkIFm\a >}'`D\ex]ʍ hBXZSPWdL2 8ъ,ȿc gښǫYl @` ey8cs|;ЁF42PikhNh8 0+6ux",!,rŅE%,'w@}C:t`&u Bhinh[](d$B(!,8\\:vO~sBASc%|U^EP h ݱk~V)e![GEƋgϞVG٤hpyܳgSN- !AM9B@W_=uڹѠ0&C!h`% TQdj։lR*7{_.UmcǏz -)Yaff3g ͲL#uv-(3/>{!pAJ9pāСݮgcc( NmMrE FKdK{BY'G{ewZ'^=A٤Vb +tGغejL12+>sں[x楥9!E Zn#k}}+;SR\UQn)t]JKKH`YЊLvV6o$&ٲe [2 c,,]r/oP}a"qؐ+PXE+-K?NX Eݦ\V8۵f^wt]&jǸ ,K`[6j:+{Orj۲@JvyPEt@GPF^l3Q&&a~/gIna}FЯ64#ȖeQ.grr @-8w,g8RIieY6j۱q~'֎@qv8=( =pA4DKA։MfrcyGM,lf4SSSm9.\`bb",fղ`[>aYIVЙG#LZ: xn݈%ס^ZqͬGDEI"P4wA > ?3Q|ߧD`֭>}ZF\fyy9GT>'R$M9G[2yjF8ceDGMy7$:81&ؼyVkH5F϶57{[74aK.Q-WW~s$o_PSbY^xZ |udllw!EHGD&'h!eP`q_qm322'?ayy~8N{9|[`[6c\xN +Q'cczl۶͛6s%J2Phtk}^B~~Ͽ~ѣ/pwȿ}DQ}ߗlgkg W3jj*ccXBPvK,.YQ6c߽ųGF)).mY- j^Aaox#%:tG&Z3DKd5 ڪ%j=ntnSoR%,"%q-'mK0Ϩׯ  0(, =^\QG%_\s9 TPT@qhT=?h'?,ZT*eU7Ups0 :I@}^N< gns y7V uݵn֚JvpK%|'J;A@i lƶV@bY=#|~ E4I϶[t:,/A޽{B*RvђWkF7;$: !Y@2s5-]72 &lr`Z4ǛzNĉ 6zX3H'BJ{d²"tg6|U. Rf`;Vj4$D'b-҄Ǵhؐf5_"_1,e2QOAp(/UqՀlm!iD4m֯JcJײmۭ]@j*0-%װtSD @2P.ý4ɓ'i6O^ܹs8u( /Z'OdinѲD.Ze`d.fs;RP{ZԳ>XPB?^(Q:(@G%A&@dnbf+QI;L9-,r*f27!#)؎mQT˚ oh 5٫'O%&&6jVt:xZhj>-l'B~z%N"hiCЙWVT,/-sqfz;~I* mys9roz;۷o_{J%R3]!-f@7ԛ%:f:482d<[m\wsW |m*5)//KՑR,%B(Nd i/Y^\+y!(Kqlvp3 CSdo,5TnFWE\5.ݦ/\4VXmccLj4@h5u+Bw:\-pR])'_~-- k B(GfJjθ%hat L̐h^xqlSad8vcGEoA`IفePCYw n/}f?fɍׯB]S%$è6t$rpMh56PDH_\%JE.~< VsRP.bD̈,қz)"ʻ{NaVe^g-MIe{ eAVEFu.j ,y*JQ1N3G23!)ɱm|?ql6A8*?iZ S?˲}?y]s򑑑pqyF(HF祒b3G3 ݨ'4?'E= /AatAYǏRQNm255;wdddsnٽ{7gΜ\.@\u]:N۶iZضUU6mɓ|P1j%L0:6d(܊\< |}toxk@!Y&mR\I\`\l@ j-XZ\vsjXhg@e>CLXy\]-?#ZMWK %!Z]u-(K젤H4yR9bU q?\LvY1eDWBX<9խvdoI]#@gccx^Ma6qTΝcΝ,//ni6j5ZF3gP((gΜa۶mx|[{evv%>WU/~opi>OqQǓO>vz!&6O?Hඎyc&7V2@ֿ|8X^4?[2U%;<fffxW8pR !f3AXyk%$+qJ@նڭ@I/"/TUJeiu8=&U lF YDn9g bdd(R9> -DZtad0q I_(.J5PJ9=ڝ<:uPr^]+>A\oZU{GJScR;i56 Aޝҷ6Q {q~tSP21-񆆾.S0רh|b/-}5:WUt[zxaPZ:ӿ=<gdii ˲XXX^c;6E!ZmDZӞxe uHfR2=})8Oꫯc~_Osy'8<{Y H[;vW^Yl4T+f&a+`Nz :y9}n(mԩV՘A˲زe V;}];/~Cq!|ǝ^瓟d.P-7Tr1 ےnCe[ٓ@ƓP&|<3<t@Yʑ[&3W*+l |fBjm[r=2Y(=}&Z>2%hF]KRsFAZAƣC0ZHou{"C٢,Bѹ(]88 ,!h0>>&6HJn).WC @_)|^gռУ [˸zQ=]?_,hz}DXkI qpK%08+74b،݄7Nq$~cN'N{n rӧO{n^~efggosx(vmqYǩ`T*J%LZQ ˤ VԺF(;mM/Ï<HcjjFpvLfLB-j9+1N' jA搪XO6HWT56%2UBp5u0>ABC`&J -5'3SZٺ9vaS#ǟ'&QJK fav!`k8;v>-h4T+3ILrY!!,Rx z0:xHLLlbbD<'կq])_2'-˲8~B>?LW~Y"5#| ]oD3«R\ #K +9u\Zz(DS)<@c}5}wEDG};".dO{KvEmӥLYR롇k #@i9`&LJ׿ e噎Nk"ȃ8 |eY _"/&Кҳ9pK 4$ n?MvC "iyyUi045\ )M]*軴MY= YcH-3)-ݸu hĊF:Ccǎ7a4M^z%VVV8q>(?xG?<:Mf޿BV%oKlEL "Y+v[G?sHR_㟬 Ӌlu!EצS^ zltgϞݳgc'$Hܸ(IDAT~:V=0ދ Em+OYϰ)-S'JW!῞&MX?@dd}REiGS[C9"TiNd7dj8%{LCu1"[:ۣ:_L3޻p;qXu @- "䦀w["Df;4@/K1rQ\e2I]db2Rq {ɺt: оopdMOi9k:C #6(pBo*2S)9X =Ȩ.IbBP~U\]="L|3Օ_&SXW'ױ;twZ޾uh*_mC GA0CV{ђ)JqlD$&h( 3=Y",+%rzd 2{ g,nPh{Rf|ݖ0َdTT[*"8-!D 8q)` ^{63:ȺC#@;(\Ff5ٿ~cd\x( 38.Pv(/rgG^XoSА.8aD=&:59k'&d%I܅56}-`0Y7L`-jb<ն}1٘b*0`phōR/f5r/ :l&`gl.5t$}:WL{ֽ%1;Z_ IzC_hsIENDB`bookletimposer-0.2/data/bookletimposer.desktop0000644000175000017500000000041711754704276021362 0ustar kjokjo00000000000000[Desktop Entry] Version=0.2 Name=bookletimposer Comment=Impose PDF documents to create booklets Comment[fr]=Imposer des documents PDF pour créer des brochures Type=Application Exec=bookletimposer Icon=bookletimposer Categories=Office; Terminal=false StartupNotify=false bookletimposer-0.2/data/booklet.png0000644000175000017500000003270511753601105017065 0ustar kjokjo00000000000000PNG  IHDRnh9{sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx}{]y{<5fFh$!! 0$\P^[yl%$xjZo\)o:@-@^ 'zK{yu>ܙOsw믿_PJ}@ iv>h>@@}"b&N!*/%SqDś͵B2_D.F~i-f[wP_ 1?#d~^ΣP?D|q * |~N@zh81qh&^&Bx iBe<ߔ'.!;>1ʇ? 19M3OeJ)E 8 I3 AA(Me} 4#/8oֿP!p=/"`(,_g?lnn5C+hJDpnaBAOED;BLJkBjR߹g/)uxb-%7C1)RDPi]2q))Gݠ~.\Vt]^ݳdP7,apWv>O|ŗf6:!F@]7 &D51/|>4(k4r@)8>[VJ `\t*M  rb@a^~<U2M|er{5ũ3.Xabb-&f$BfOrZ?< qP*M&85H ̑L]eccN(~q]x4O 82`sSa{BmDuO&$p@]jm0 O @nЌ3O?B\cpѢi BL%DZHw+ x1hJT(i(#'ՕJJ d:|ȷ!n40MR uA!v>ӧ6h`o`VTWDvkHAfq0=5 ]ew*QE|h(`*pV/V7Y $R/.irOo\yɩ-Mhl蚆aM\/عtԙ#1`ts]]7RJ۩A7"L'2`u;&2iyX؈qLܢ\C'eAH%`^Yb^/2He0tM4 D6jWnu{oRocBqLm4LWr̝J6ͬ . (.% /Pԁ-?"#T%FZ# EXP o{ouٌG}mmWUX{48j0MR)@wwwZn_] l9r9Xy+||k+I6ؑ)hhhӰ, gΜ%Kq)EEv G 217mK#VCOw'}_!6UYJhfpu]JBt]iaO$ W4sVkm[lK/m\ wn3~%#$0_TCϣVR,躎SSSu3338{{`&FF.` BS%IYES<$e&c>czUR&AG>pAO<#\(m  Cu#PeYV0 swwfZWZY텦i‰'0=3Zꛄ%,[Ź:VҬaAgrV.J^TٮQ8z({SJ\uu@7綂Ҁiy4Fk477czzr˟1=R@3ҹ{@Ӵ0v܎ϣR`||vFoo/FGGQ,tRx-׾59vpڲp]'GӐˉВ4JH 8{,tMGKK mۆ+V`bb[l3gpwq,_333^F鼡n, (&&&055 ckޤmנ:ڰtp)-k׾vWoHj|bgϝCR8 UԄFX038C-|)$ !s #S3sfn(6pQXuZm۶J)fiwƺK,+>"D4CJ4ԡrlT*LMMbrrFTذm;T4MG!GOO/ZZZO]ߒ+)I0FGG(hK):?V͏Z?%+bJ;p /Vq P]ꗈSUYKߐ,еaQSRCKld^-CO`:iX,ӽ~ʕ2Džޔ0PDC)!xRZJ*@k|CՊ"r"F4]4siu v~@E Js9Ti&Ҁp0WU$ܫ.K< Mc?GE DΎir@Ĝi.R D.+fmϞWwEJ1@{6>7MbkPF`vXRM199"E4FPP`&Wٛu9r[!8yPTp嗃RR%Kͨ i-)tPNthץ8|:;;eদfڵ }}}Ξ=~% r0 cqo% XS$ t k\s-uB!2=:IBB̙l0!Xj%dI /0-i5fi26fOR,EBSʼn@6'2G#lǘ".2=AYqR4L8^i]CR#TゥxUCCFf|n-_Ӡ`>`H<5ԝ"ٕm([N4c,~QdJ> .8"̖$3~(Րp4pauQ B>id uz )%rhSOs3fLeb#RP#@JTtV6|{u"p>pNr੾4Nl:,Rh{QlđQ! tv3Hh{ Mġ; w-㸞"Ҿ?[KxY)BhWDxg\DjUeMũّ\QlBIW`@eW(yFGqFڵ ذa6mڄM6%&{P!;zжmOI ~Gƍgm6z5ҡH'z׍2J4ToU:԰qgt,]0-_0- L~mՏ/xy9ti @JaXNV >[wN_/oF N8&0.k3.Hhyv:jvwfRG( D Ѱ|[[[+`AIJJ1q^F~L:7@aSdI%։$8Sh+d" ,GEXHNF kȡ!?$1T)T ST1[\ES:S'u.LĬneqers KA$.#!@f1JЮK"9Z13SBssvУb.jI3d*U{{ 7EHK#0 MMMlIRxIen]o!zp/ۼ9JhMZNN:|>nnii}MӰl29ra`ttk׮M+Lۯ"{`@Nm ,͎PTU;{k0>>aj.q099!_ַE \/1J̠M#ruaVYp4 àpY(׿&S N"|sHK1%遙†z!)M,4tv4M467_"6 Z@?r_Y\{l>g Oi j#4 '/6{(ʫ+ Xz()[Ӭ-XQc^ѱ'QT ~'PN @xRʅFȧwH5g?ԆD+-]\$5aDR└*[ڪY/ Ml=QguRVPeEdį f eb%t17X,-(~|@3ǘCfUT`b(Un9sOчBp9Sl2䔿.YKj&&'NW~eU`D}a&zzz.u"E!y2 &11ݔiXl|}A0$J'y JܯիWVg2<yOl:Db<+*Rk1((-ફ߂H׵p|VR9N!#M'd3gBYHlD& F^㟇ϚOzsxʪ~)f밁Z'p013 ad2 D.)#ia OOAEpT9Q6Y `4SQKRQvg.Faty,)ĉ,$`UT$̒mQ\nyQ05=> z:re:f<#E9(QQH,J%~`͚5Y%KhjjBCC&''сݻwc(Jhoo477Ar˻OXSE"0B +RyULNNkQX`l4M8,X&8pK.}O\B'Бϳ-d"M;8:0ЏW\M^i܌rήNގBW@wO7LDCcCx=,ѼSShniƙ3gspa 0sN8s|_ǚ5kҫQ HHrSWъ:!K,u]LMM4MaA[+*ZxWNϠmc a6a޹<_yx022?C5C4 G3<r ёYH7 ah 't'+,ahq9?$KooJMӤRZ;KŴuEuuMy0\F]K !:ƖrykDԬM32 yr܋Lڏz/~w#U5өo!-"NDg8h#- ,K\*p1JYaF%=J628q-ҳ3+^FJ'T| ,(U pac2%TЄ ę`J w9%EyB-NX H Rg9TK'{~m bjj Rr̪i Ju$M::;;1:: Bb رV*V\9Uz׉gHw@jz+EڈZZ[Q.P*peR4MԄ'?[ou7 ?~w`۶mشi8)+W'NO>kbغu+188qpٳغu+~~s3Ҙ4WlLCC,]6rf,XF.gbݺku{.lٲ-BVׯGsK3qUWa8uJT*m3O?+V]+vիpQ.iX<0˲P,w^\}ճ) + 8%NͅpkEVWJI.**D,K&yu]ׯczffSJ!#,D \DXgfY)qݛ׻]n~$*` n5-&"6M$l@XO+Ȓr,3 N%MS1QdDzaMF06 RG:4[4gΜETA>o;v}8}4z{=]̲,LMMattip]gΜAww7 l$lFkk+.\r9 ۶ܜZ) 5] W( :BdJ)v|pCCC$ֶ##ݍbJ)&&&`ޫA;6LMMR^2ΝCoo/A\].!+C.mpcfeMv_xgކGԌ8y|;v  `bb!&&&Q(`&'P,6`߾712rKԌ/A)pA?~ql?1 3d&KAq ׇJzzzqyA7 cbr'NK]457 @GglFͮ E.arrc::ڡirî];ApP~@/6zAPϟfOe,?п"zOJ$Wr} =;CXXp(Iw#HW>MQhh]hѺiZT9+*տpQ/6q] 7ܸۨ(,=oTnz(~Z8B.kP^lSމNw"#EP0ƗYb)PCqn(aBξTT:mdE&Ւ_uiY3R@;\ O6`$~P * ~S&@$ţ^T@\q/RE SSVa455o7*JvB0::foW^P@\Fcc#ajr\,nobk6X ܄Ƥvȉ6U"G|B8GxbT*J%@{{;BcyxxK,mBX@GGr8w" \ߏB5CP(0Hq Ij8cJ-(BJQ9( oT.u?Z̶`zzXhffJhllP,1996kXb,¹s`c\ΝҥKq =6IDATz[lߏ۷cÆ pWȇmH$D-Gʺ)&ZcjHdhhhD\ g8z-tvv¶mEtvvbddre4L?vib.abfzccc( Vk,|_7ߌCm|FR>ju%8aê~qBH DREeKǍBg㨟O4IS2G9y{)J{{x¶ {;pZ5<>I HQ) pٵnɔ$MxJ(bu]/o8Y>dJHRL] vނVIle.Wr2nlub* 'gaij߳m7W@$'&-)X>ERZDl]PC5aeG=@-\~b TtD'zdp5[(YƗ1".;eu^"gdu".B/qĒ!X?RANʰu|\A Dlbb'M$FW_)yBqSڐԞfIbg*$dN `C]iM"*)S\#d!Qnb%/vS*GU KL`pId٥5 MM*'9 RգfdhXdxȁ$m4'υp9,kِ*A2${ SVi5*:4x/R;d@f' n#D2 ϔJ~&GISjFB-u]%MEYY\oGKUQi0Mve8$0_0 Xh"w?a۷g[,46oތ뮻?8.߿'psVDV)=:zt]_ڎbbӧOZ 9BV(0M'O />x㍨Vx衇i&書+cÆ a6mºupZ"abb?Op=`ff/2N8{---޻c nCi'hG,%\|J=vГƎnibo??vJ۶mƍ>(>Oa.\68p_Og]GO}S>sO@IfV-ѼB(K]85~'FΞzqm`Dxi*+M`l| 1w1й!tuw%J~ȽCE G}9;vc~0ەB?3tMD.5g wv˖{W^:>τY:dP ,^<},rc4A6Gٔ~"Axҙ]8\%16s[{{ɓ}\7zJ+Q'"'N0JtRGoUY޽0 c9LQn¡"w7Q ~9OZr֞ _J'.0pBQZB"C\EZFdU7504*7<VRH,+3(r\T5j5.\)O.*DI4fEЈ1~Y8XU~st}={]2QGX?Y{ ۈ\ŖgMMMrK/޽> 088ĉk3`bbw}N\IsV@%:m[C/]:N\˲N>{B4TYj0m)t]|]LAR7I+_y\ /CID^$fHGI5sKݲXtK0%b0o\ڕpOxtuwwpŏNEQofE3 w𫮶KF|x__{,GY6ˑ4H$gfft%oCCsA^`27(TlTBe}%& emFJ.^NdII(p'r1$=]h f\7V+Bq5O=* ۶SNU3 "Hgnr []u!+)ۿ?} /ƩS`6:::|ꩧpwd+{r[ OW ?Jrg~ ,@ReY 4 Bvލuօս2!gYYPe Qgd Y ~ .Y~P tvubrr]]hllD.۱dG?#vpV]Ÿٟattǎ֭[n::} }яuo>| tE"q1` Xa yƧCi;U/\jCAeB剟!שv!uByoT+rgg^0(ȑÏp%Km\8S=Ƕs]ض}A(” ?UayHsWFR4(cWo>QYZ#{ ޫ!qc:z̍) Y. Oe$ի2 (ğuKd!Xv0_&nP)׬ucླྀ.37i֖yMu\PJiܷV oq=u4x J%_z .V^-$*f6%S9ރ%vիW`PbR Qx;Cx/4-(d2wq%>͹!BUj,I)1U=[.[`9%`)tt1'ѣÓ\X%Ac~1}aAv^xlBi$SnsT9(%56@-l@L e+#a4WX;x?zfk|x2i5?M_H M?p+Fuhp&zuD|_u$ڍ XʮE!teA)%F-Oo՚F)u ii#ZOD˴ PJeX( (k"qA!GRTvxX-Q@B~;8v,uLPhԻ#Kc_(D5!'f&T~RB}sCG\.W:xQx<-tΏW~?CMMMݶmͻkӯ1z~) {$8>KHx4z4ͩ͛7  t@JSؖrV&)/:gAlS 2< Lx s'!Yp_+e"&|jE ?K[?vpcF23!x xfgIR\sw~n߲gT: ̲OL" @XÜRRHRm@h,jLxc In/% "RDa uxó$^0_*I߬:oR$T|RYR4Ic][KN\X&g1,NIƣ9hnWzX_UJ" 4G]IENDB`bookletimposer-0.2/data/bookletimposer.ui0000644000175000017500000007651311754704276020340 0ustar kjokjo00000000000000 False 5 center-on-parent True normal main_window BookletImposer 0.2 Copyright © 2008-2012 kjo@a4nancy.net.eu.org Convert PDF documents between diffrents page layouts http://kjo.herbesfolles.org/bookletimposer/ PyPdfConv - Utility to convert PDF files between diffrents page layouts Copyright (C) 2008-2012 Kjö Hansi Glaz <kjo&a4nancy.net.eu.org> 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/>. Kjö Hansi Glaz <kjo@a4nancy.net.eu.org> True True False vertical 2 True False end False True end 0 False 12 bookletimposer.svg True False 12 True False 6 2 6 12 True False 0 Output _paper format True output_paper_format_combobox 4 5 GTK_FILL True False 0 La_yout True layout_combobox 3 4 GTK_FILL True False 1 2 4 5 GTK_FILL True False 1 2 3 4 GTK_FILL True False 0 _Output file True output_file_chooser_button 5 6 GTK_FILL False True True True False 0 True False False gtk-file 1 False False 0 True False 0 5 (None) True True 1 True False False True 2 True False gtk-save-as 1 False False 5 3 1 2 5 6 GTK_FILL True False 0 _Copy the same group of input pages on one output page True copy_pages_radiobutton 2 3 GTK_FILL False True True False 1 2 2 3 GTK_FILL True False 0 none True False 12 True False 6 6 True spread False True True False False True top True False True False vertical True False 180 booklet 6 False True 0 True False Produce a _booklet out of a linear document True center False True 1 False False 0 False True True False False True 0 top False bookletize_radiobutton True False vertical True False 180 linearise 6 False True 0 True False Produce a _linear document out of a booklet True center False True 1 False False 1 False True True False False True 0 top False bookletize_radiobutton True False vertical True False 180 reduce 6 False True 0 True False Put _multiple input pages on one output sheet True center False True 1 False False 2 True False Conversion type True 2 GTK_FILL True False 0 _Input file True input_file_chooser_button 1 2 GTK_FILL True False False True Open input PDF file 1 2 1 2 GTK_FILL False True 0 False False True False True 1 True False 6 end gtk-about False True True True False True False False 0 True gtk-help False True True True False True False False 1 True gtk-convert False True False True True False True False False 2 gtk-stop False True True False True False False 3 False True end 2 bookletimposer-0.2/data/reduce.png0000644000175000017500000002730311753601231016673 0ustar kjokjo00000000000000PNG  IHDRnh9{sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx}yG/^:[,e[`"95/Cw X! vfXZ2L[v[mjIu~geueeeVe~-ˬWw~//+306M,dxަNۀ~m@MT H!S˒!2/gݘfyP#qyq@6aKt.Fu|\|W.\=_¹qȧmqײ; FCwNӫcٌv]t<a`,ĜM8ғU,T$wL (ҙZBHlQٙ_&%&FPݠ~<םi20,ƚ̢5jU-˪,ZX`IA JaJȘ,a|ct|?3{")0@Ò a7`HGJ(в,E%̕~|駟~; jY3,jYi|)⏹־{IuR  H㔋E$&e~8J.iB`>?~ |9.;\h7|t.w1lyHNR{՞={W@љ$P!¨?  P * < W\;NPNuJ(Hc 0 r}7 ^9B)EkՠF j p"/:ӈl /-Wcq,L(cWK쨁ygN@2=r%3j@eV˲@)MW J*mG@ h'#cBS: LÀHP**d `UHjtL/3԰JsPDR ٲ+P(i&|bHF>VX"N! ÀHm/'@@{`@])دc t+Ff8{,6oތR1tuu!ò,|'JR;`DATi2yB~ĩķHH~A^GB*46n܈l6cǎa``L󘚚¦MP(^\GswLBSk#bfD1SD@?cXvY*l6AT*00xS?7t#V^w B8(AbOiHSikh }}8?y===Xo[ر7nCG \(gi,4 R)W@^jW/_|^sDooo* QAZ'D.R ~;zzzK(]78#JX*> ͢Zͣlմ@ُSN`V;uC]`]yoPdYjkhH1(,u^i,()t;:JuXdpqQFٳfj j*:Z-LD` >''Ozu$΄9Jhi9!`^%@ 0nc7QuYSd>S>?5,0췅l!HSh4Z-X.f͔T$_/_-\ JCSFohY+!Z> @vUy&hmfj?ҝ5LPi``YQ=Npۮ4KCu[|^ah6(x;ށrJlٲ333`P( '+EB\{!'N9Fc1# * ֯_Z3g axxsss)I2 RԢr``o4!$N4kzBڎoww!XbA099K.Y~R&٬vԉvj|TSQaCn^C)mۮ8 ]WJ:J9uKz+%QTja9(* f[c=kڿbz\#½|*_*m%$a[rLiuhw14G?&eDnjSDB12' `0@ d00Ќ1F<^xW"&lMERLv &o&W.\Q#X@ [T29[Y ;ؿʜrH$\mpuH*zԢD:=SB|gs>of^f R҅27.$ 1]lІ8J$)cg /~\wux~w=npF{} P_n ! ?088B|O>$n`U]ֳ:C>˲088REivmxۃ}C*Q'˂bp]!" NcxxekU^\r֪]زe V\Z}XS DXhyVYFxQE°tYL`u( QXB^噸W3xw'@ͿKe?K)+~KSJ1>~(w(tP hWD&*]V( $j wx&D\ [JUfIQ MRp ކQH{ϐDʲdPR,ej󼬒jhg(©La bnyU; X5CGB(̕! Lk%GIg9B{WaI#d2i/$M/ ֬Ye.E dP[Q܃3|֯ Eq8Oxy[D.,/*+|l@ 0#׭d?~pl,ju\n5L-Jbr }_8zc.ݴp;6 L,I50GJrEc` W\J@ x, !TU3|I˚HpuPI7v2"pݎi1=R7\dmQlt%s&}r%[> gYy޽7|36n(=4$2Q&{f` N.cHg2(jX_@__ʂ}|VXĉ'bhx p 3_f ozu%(.`/*tZMa@/U|ϗ>я3_!_,*vFN^$ ;IM94 g1:A-OZm[$H!J)N8y1tM!9a N61F&&8 Ewd$U~Rb{]d/VBĎW"X'l,ZmXiTS%?)J| = ݯB㯟@Ww7::֭[GbågϞť^]8jrl|\ ׏Puh0Pߏq ;8q[\ֱzYJɤ;In3%[%XY VZsXj5jP.Q*Obǎ8}4z)r-Kp! b߾}8vn ȑ#7pj6l؀z_Ӄݻwczz7tN>h4x>g3@>7]]]CwW7zP,l"W\q*vލ}s`a||ΝC:?|+8s &&&}vڵ ?;4wu.rOܽXxU d.M(<%b&<= r?fl5=eA*A$rJ.:-ĵ&Odl׏~;NēIv &vP7⠦3ǀ\po$A%l#&+];Vw1F8E:Z*o_*%bP h4FSb/.|Z.9ћBaM.#ahhRLNNbըT*X.P(R`ŊHӰ, SSSE68|>l6 0J033{w<H|C>EU­R)c8z(VZFZ>LMM!J 0Կlbbbh6C6uxڇbJiyMXDP(r1?>IP1A8f0==I)=zQLztGĹsE:Faq~} %eUkA&A&$,SX\T*R]~ JFG_ñcc%/rSݹ ba^{`a~g #esUkdh4x}VkF: LabbtfXXX@6iNq!?fB:}Y[g} ?~3x R.̠A X$xI6)۱.n Jgb֬YVZE^GX fffvx-Z (#>?ˣX*zի>`\.D4t?8"Ekc`` ÀeYFZCWwΌ1^4 Bj㼐F" @>cJXG=* 0MC hؐNI+wfN1;;Ǐ{;pL&L&ٙY \P vtݶON7w<$T6킘KQw4Y+.cɽLF!`KsX06W(QEF5F*8G-`D(H(ٛBա8  $I@);(Kr{[$yp Ig7/Lyhb $R8nK.YO QGyFQf8>l1 MXIx媅2t'#PWQ`2.G&#ZM϶)CGj/ TE 5f=HX9s$B#*DeKY'e|SHBƉA14&E7(%*F+d*K@[tUWgG%m*011>e077^̗Q*\.RRB Y[dMT?~ŢO)\y3&hj!/`zz@__(Oo1bXq~;Ǒ2<:]i{02RP,Q5Hz tBO|֭ 9+eǡCb޽[1>>5kĉصk|Aj5ؿ?Z-l۶ Oڵkbll slڴI%F'9IB/PM(6 /Ѯ};ekiĩKT/$K: R8ge{F5q@dLaU#!աP0b3)L.M&.Kb]O84*i%!"D Y* >I,uQ+)D7":{,<Q,^XXa*& /tGaX*wHet)ttcvvhﹴ'=Xhdž PȂTDT Hj"e OGi;EXE6(`yƍqaXzk׮Ν;я~rk׮eYضm*fffQ.!d3:op+'՚1΍R'Oo87l6ATUu||6lՅM6,|W^ 6PO!ںu+py\J+WLΈ6>r8P}Wqga+lp]wuE[ A{ltVtF2'ȆV%|,G[KԍJ_YHU&}0#}P,˂iF"TGGD{AxǠ@ǹϔRCy{p~SS'Ad"LB8 +5r]#bj )+ 44r@D$ jCAQQ%u1 j+?^l)v\ EE (3ǁIBzr/Hr?,uP(, Pn3;;ZB0`q}&<|+B$ѢXE?}bJ%mķé)4 KEO BY"uBۆiX(ɦv{-[xo]oV/#GgܹҐV!Br, ^~\F(. ;޽~q7(֬?EXW eR3:ab\スL, gCa4 .`\~OwwkhFQ$*^DH#y  |geQ9puo$+\td2\q=8+C^VDC>OLbyᔋe ࣬RW$OMXq ޟhEG3\J@'T>&w Gg# DWUTmLa0!m7Aüzp맂lvI@I-mݗLN xHPZmjİOd2,4FJӞWLG%gx7*TP,XOb<^W=uPIhN!–0b: ر7PՐغu+R}Q}?//#yX}}}ꫵ9(J!s۹|b>Ss&PJ1rt;>waaj[nܹ;wķ-|_޽{q)on݊׿C-lHn~SM}~ӟFK1H7 qN4lL~s.J Py v;ZSX%0՜aQC7p}JEikKg 0zfUb7l05VR5xCX_"Mdz~_m!R4ohv=A7ppHF!DWsڽ\/=\P<`;VF6, j240-r mǷEaLݟxE|N/b(xd@*94U$$hunȁ?ŅmLS[__jHrM!6Jhf݀"tL3aQH4!4p>_-`g_e E) 7yupR!e<%I܍wH G$"8@v5_hNlp(E@?a0FȧpI^M;qqa4 &j(L<(aA"oƨhZH#-Ɏ!OdpD`,5!UR$|Æ@N;.xy {Kh&zK3m݋'Օ] jF7VRh*{{sR6Y>) ˍH:"%\iʫ ZjhZ]DX0u NPjx!/I@*k2J3H@K$Td((KBx`t _avE{@ֹ ַ_XjpWWc0)LJ# gBZbCQ*lo?$t/3|n`q4yre7G"J)&i4V\. sI@eQ0PwDVfC u.w7>Ý Ra$p TA7; 1"3Y-l6aXZ aG~ 1y o |s~+%!.)ЦvtdeHͿ,|~l*r,qK{^ZՄ-ukUP0 [ù8nZ 2ǐ܋D$~E e"] IVx Cd|Ts!ILq?<)RP*Q.=Q g(T*7]LV[v/V|1St[A0Hi'QT{?O UzNP;n*%xa@n)bR%ny+H)?R: 4N>{zڑIbi v1PR)c@U~P(vVjNQR JgA3/f{1С/tpUXy[rMmڥATIENDB`bookletimposer-0.2/data/bookletimposer.svg0000644000175000017500000041550311753600647020512 0ustar kjokjo00000000000000 image/svg+xml