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
29
from __future__ import print_function
36
from subprocess import call
40
IMAGE_DIRECTIVE_PATTERN = re.compile(u'^..\\s+image::\\s+(.*)\\`\\s+$')
41
DIRECTIVE_ELEMENT_PATTERN = re.compile(u'^\\s+:[^:]+:\\s+')
43
class Converter(object):
44
def __init__(self, srcdir, destdir):
46
self.destdir = destdir
48
# Process .txt files in sourcedir, generating output in destdir.
49
def process_files(self):
50
for filename in os.listdir(self.srcdir):
51
# Process all text files in the current directory.
52
if filename.endswith('.txt'):
53
inpath = os.path.join(self.srcdir, filename)
54
outpath = os.path.join(self.destdir, filename)
55
self._process_file(inpath, outpath)
57
def _process_file(self, inpath, outpath):
58
infile = open(inpath, 'r')
59
outfile = open(outpath, 'w')
62
if foundimg and DIRECTIVE_ELEMENT_PATTERN.match(line) is None:
64
print('Fixing image directive')
65
# The preceding image directive has no elements.
66
outfile.write(' :width: 85%\n')
67
outfile.write(' :align: center\n')
70
image_fixer = ImageFixer(self.srcdir, self.destdir)
71
image_fixer_lambda = lambda match: image_fixer.substitute_pdf_image(match)
72
line = IMAGE_DIRECTIVE_PATTERN.sub(image_fixer_lambda, line)
73
directive_match = IMAGE_DIRECTIVE_PATTERN.match(line)
74
if directive_match is not None:
75
image_src = directive_match.group(1)
77
print(('Image ' + image_src + ' in ' + filename
78
+ ': ' + line.strip()))
85
class ImageFixer(object):
86
def __init__(self, srcdir, destdir):
88
self.destdir = destdir
90
def substitute_pdf_image(self, match):
91
prefix = match.string[:match.start(1)]
92
newname = self.convert_image_to_pdf(match.group(1))
93
suffix = match.string[match.end(1):]
94
return prefix + newname + suffix
96
def replace_extension(self, path, newext):
97
if path.endswith(newext):
98
raise Exception("File '" + path + "' already has extension '"
100
dot = path.rfind('.')
104
return path[:dot] + newext
106
# Possibly use an SVG alternative to a PNG image, converting the SVG image
107
# to a PDF first. Whether or not a conversion is made, the image to use is
108
# written to the destination directory and the path to use in the RST #
109
# source is returned.
110
def convert_image_to_pdf(self, filename):
111
# Make the directory structure for the image in the destination dir.
112
image_dirname = os.path.dirname(filename)
114
image_dirpath = os.path.join(self.destdir, image_dirname)
115
if not os.path.exists(image_dirpath):
116
os.mkdir(image_dirpath)
118
# Decide how to handle this image.
119
if filename.endswith('.png'):
120
# See if there is a vector alternative.
121
svgfile = self.replace_extension(filename, '.svg')
122
svgpath = os.path.join(self.srcdir, svgfile)
123
if os.path.exists(svgpath):
125
print('Using SVG alternative to PNG')
126
# Convert SVG to PDF with Inkscape.
127
pdffile = self.replace_extension(filename, '.pdf')
128
pdfpath = os.path.join(self.destdir, pdffile)
129
if call(['/usr/bin/inkscape',
130
'--export-pdf=' + pdfpath, svgpath]) != 0:
131
raise Exception("Conversion to pdf failed")
134
# No conversion, just copy the file.
135
srcpath = os.path.join(self.srcdir, filename)
136
destpath = os.path.join(self.destdir, filename)
137
shutil.copyfile(srcpath, destpath)
140
if __name__ == '__main__':
141
IN_DIR_OPT = '--in-dir='
142
OUT_DIR_OPT = '--out-dir='
147
print(('Usage: ' + argv[0] + ' ' + IN_DIR_OPT + 'INDIR '
148
+ OUT_DIR_OPT + 'OUTDIR'))
150
print('This will convert all .txt files in INDIR into file in OUTDIR')
151
print('while adjusting the use of images and possibly converting SVG')
152
print('images to PDF files so LaTeX can include them.')
156
if arg == '-v' or arg == '--verbose':
158
elif arg.startswith(IN_DIR_OPT):
159
srcdir = arg[len(IN_DIR_OPT):]
160
elif arg.startswith(OUT_DIR_OPT):
161
destdir = arg[len(OUT_DIR_OPT):]
163
print(('Invalid argument ' + arg))
166
if srcdir is None or destdir is None:
167
print(('Please specify the ' + IN_DIR_OPT + ' and '
168
+ OUT_DIR_OPT + ' options.'))
171
if not os.path.exists(destdir):
173
Converter(srcdir, destdir).process_files()
175
# vim: set ts=4 sw=4 et: