3
 
# Modify reStructuredText 'image' directives by adding a percentage 'width'
 
4
 
# attribute so that the images are scaled to fit on the page when the document
 
5
 
# is renderd to LaTeX, and add a center alignment.
 
7
 
# Also convert references to PNG images to use PDF files generated from SVG
 
10
 
# Without the explicit size specification, the images are ridiculously huge and
 
11
 
# most extend far off the right side of the page.
 
13
 
# Copyright (C) 2009 Colin D Bennett
 
15
 
# This program is free software; you can redistribute it and/or modify
 
16
 
# it under the terms of the GNU General Public License as published by
 
17
 
# the Free Software Foundation; either version 2 of the License, or
 
18
 
# (at your option) any later version.
 
20
 
# This program is distributed in the hope that it will be useful,
 
21
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
23
 
# GNU General Public License for more details.
 
25
 
# You should have received a copy of the GNU General Public License
 
26
 
# along with this program; if not, write to the Free Software
 
27
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
34
 
from subprocess import call
 
38
 
IMAGE_DIRECTIVE_PATTERN = re.compile(ur'^..\s+image::\s+(.*)\s+$')
 
39
 
DIRECTIVE_ELEMENT_PATTERN = re.compile(ur'^\s+:[^:]+:\s+')
 
41
 
class Converter(object):
 
42
 
    def __init__(self, srcdir, destdir):
 
44
 
        self.destdir = destdir
 
46
 
    # Process .txt files in sourcedir, generating output in destdir.
 
47
 
    def process_files(self):
 
48
 
        for filename in os.listdir(self.srcdir):
 
49
 
            # Process all text files in the current directory.
 
50
 
            if filename.endswith('.txt'):
 
51
 
                inpath = os.path.join(self.srcdir, filename)
 
52
 
                outpath = os.path.join(self.destdir, filename)
 
53
 
                self._process_file(inpath, outpath)
 
55
 
    def _process_file(self, inpath, outpath):
 
56
 
        infile = open(inpath, 'r')
 
57
 
        outfile = open(outpath, 'w')
 
60
 
            if foundimg and DIRECTIVE_ELEMENT_PATTERN.match(line) is None:
 
62
 
                    print('Fixing image directive')
 
63
 
                # The preceding image directive has no elements.
 
64
 
                outfile.write(' :width: 85%\n')
 
65
 
                outfile.write(' :align: center\n')
 
68
 
            image_fixer = ImageFixer(self.srcdir, self.destdir)
 
69
 
            image_fixer_lambda = lambda match: image_fixer.substitute_pdf_image(match)
 
70
 
            line = IMAGE_DIRECTIVE_PATTERN.sub(image_fixer_lambda, line)
 
71
 
            directive_match = IMAGE_DIRECTIVE_PATTERN.match(line)
 
72
 
            if directive_match is not None:
 
73
 
                image_src = directive_match.group(1)
 
75
 
                    print('Image ' + image_src + ' in ' + filename
 
76
 
                          + ': ' + line.strip())
 
83
 
class ImageFixer(object):
 
84
 
    def __init__(self, srcdir, destdir):
 
86
 
        self.destdir = destdir
 
88
 
    def substitute_pdf_image(self, match):
 
89
 
        prefix = match.string[:match.start(1)]
 
90
 
        newname = self.convert_image_to_pdf(match.group(1))
 
91
 
        suffix = match.string[match.end(1):]
 
92
 
        return prefix + newname + suffix
 
94
 
    def replace_extension(self, path, newext):
 
95
 
        if path.endswith(newext):
 
96
 
            raise Exception("File '" + path + "' already has extension '"
 
102
 
            return path[:dot] + newext
 
104
 
    # Possibly use an SVG alternative to a PNG image, converting the SVG image
 
105
 
    # to a PDF first.  Whether or not a conversion is made, the image to use is
 
106
 
    # written to the destination directory and the path to use in the RST #
 
107
 
    # source is returned.
 
108
 
    def convert_image_to_pdf(self, filename):
 
109
 
        # Make the directory structure for the image in the destination dir.
 
110
 
        image_dirname = os.path.dirname(filename)
 
112
 
            image_dirpath = os.path.join(self.destdir, image_dirname)
 
113
 
            if not os.path.exists(image_dirpath):
 
114
 
                os.mkdir(image_dirpath)
 
116
 
        # Decide how to handle this image.
 
117
 
        if filename.endswith('.png'):
 
118
 
            # See if there is a vector alternative.
 
119
 
            svgfile = self.replace_extension(filename, '.svg')
 
120
 
            svgpath = os.path.join(self.srcdir, svgfile)
 
121
 
            if os.path.exists(svgpath):
 
123
 
                    print('Using SVG alternative to PNG')
 
124
 
                # Convert SVG to PDF with Inkscape.
 
125
 
                pdffile = self.replace_extension(filename, '.pdf')
 
126
 
                pdfpath = os.path.join(self.destdir, pdffile)
 
127
 
                if call(['/usr/bin/inkscape',
 
128
 
                         '--export-pdf=' + pdfpath, svgpath]) != 0:
 
129
 
                    raise Exception("Conversion to pdf failed")
 
132
 
        # No conversion, just copy the file.
 
133
 
        srcpath = os.path.join(self.srcdir, filename)
 
134
 
        destpath = os.path.join(self.destdir, filename)
 
135
 
        shutil.copyfile(srcpath, destpath)
 
138
 
if __name__ == '__main__':
 
139
 
    IN_DIR_OPT = '--in-dir='
 
140
 
    OUT_DIR_OPT = '--out-dir='
 
145
 
        print('Usage: ' + argv[0] + ' ' + IN_DIR_OPT + 'INDIR '
 
146
 
              + OUT_DIR_OPT + 'OUTDIR')
 
148
 
        print('This will convert all .txt files in INDIR into file in OUTDIR')
 
149
 
        print('while adjusting the use of images and possibly converting SVG')
 
150
 
        print('images to PDF files so LaTeX can include them.')
 
154
 
        if arg == '-v' or arg == '--verbose':
 
156
 
        elif arg.startswith(IN_DIR_OPT):
 
157
 
            srcdir = arg[len(IN_DIR_OPT):]
 
158
 
        elif arg.startswith(OUT_DIR_OPT):
 
159
 
            destdir = arg[len(OUT_DIR_OPT):]
 
161
 
            print('Invalid argument ' + arg)
 
164
 
    if srcdir is None or destdir is None:
 
165
 
        print('Please specify the ' + IN_DIR_OPT + ' and '
 
166
 
              + OUT_DIR_OPT + ' options.')
 
169
 
    if not os.path.exists(destdir):
 
171
 
    Converter(srcdir, destdir).process_files()
 
173
 
# vim: set ts=4 sw=4 et: