mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
Fix several issues with instant previews.
This is a collection of changes to the python scripts in master made for trying to sort out the mess that had accumulated about previews. After this audit, it turns out that bugs #6369, #9354, #9508, and #9510 are now fixed. If pdftocairo and epstopdf are vailable, it also makes the conversion performed by the legacy conversion paths much faster and improves the quality of the generated bitmaps.
This commit is contained in:
parent
0e2ea9d48c
commit
b3d2ffc0fe
@ -42,6 +42,8 @@
|
||||
# * gs;
|
||||
# * pdflatex (optional);
|
||||
# * pnmcrop (optional).
|
||||
# * pdftocairo (optional).
|
||||
# * epstopdf (optional).
|
||||
|
||||
# preview.sty is part of the preview-latex project
|
||||
# http://preview-latex.sourceforge.net/
|
||||
@ -56,11 +58,11 @@
|
||||
# [legacy_conversion_step2]
|
||||
# 2) Call dvips to create one PS file for each DVI page
|
||||
# [legacy_conversion_step3]
|
||||
# 3) If dvips fails look for PDF and call gs to produce bitmaps
|
||||
# 4) Otherwise call gs on each PostScript file to produce bitmaps
|
||||
# 3) If dvips fails look for PDF and call pdftocairo or gs to produce bitmaps
|
||||
# 4) Otherwise call pdftocairo or gs on each PostScript file to produce bitmaps
|
||||
# [legacy_conversion_pdflatex]
|
||||
# 5) Keep track of pages on which gs failed and pass them to pdflatex
|
||||
# 6) Call gs on the PDF output from pdflatex to produce bitmaps
|
||||
# 6) Call pdftocairo or gs on the PDF output from pdflatex to produce bitmaps
|
||||
# 7) Extract and write to file (or return to lyxpreview2bitmap)
|
||||
# metrics from both methods (standard and pdflatex)
|
||||
|
||||
@ -74,11 +76,13 @@
|
||||
# is required in certain cases, if hyperref is active for instance,
|
||||
# (step 5, 6).
|
||||
# If possible, dvipng should be used, as it's much faster.
|
||||
# If possible, the script will use pdftocairo instead of gs,
|
||||
# as it's much faster and gives better results.
|
||||
|
||||
import glob, os, pipes, re, string, sys
|
||||
|
||||
from lyxpreview_tools import copyfileobj, error, filter_pages, find_exe, \
|
||||
find_exe_or_terminate, join_metrics_and_rename, latex_commands, \
|
||||
from lyxpreview_tools import check_latex_log, copyfileobj, error, filter_pages,\
|
||||
find_exe, find_exe_or_terminate, join_metrics_and_rename, latex_commands, \
|
||||
latex_file_re, make_texcolor, mkstemp, pdflatex_commands, progress, \
|
||||
run_command, run_latex, warning, write_metrics_info
|
||||
|
||||
@ -229,6 +233,7 @@ def legacy_latex_file(latex_file, fg_color, bg_color):
|
||||
\definecolor{bg}{rgb}{%s}
|
||||
\pagecolor{bg}
|
||||
\usepackage[%s,tightpage]{preview}
|
||||
\IfFileExists{lmodern.sty}{\usepackage{lmodern}}{\usepackage{ae,aecomp}}
|
||||
\makeatletter
|
||||
\g@addto@macro\preview{\begingroup\color{bg}\special{ps::clippath fill}\color{fg}}
|
||||
\g@addto@macro\endpreview{\endgroup}
|
||||
@ -297,7 +302,7 @@ def legacy_conversion_step1(latex_file, dpi, output_format, fg_color, bg_color,
|
||||
# Compile the latex file.
|
||||
latex_status, latex_stdout = run_latex(latex, latex_file)
|
||||
if latex_status:
|
||||
return (latex_status, [])
|
||||
warning("trying to recover from failed compilation")
|
||||
|
||||
if pdf_output:
|
||||
return legacy_conversion_step3(latex_file, dpi, output_format, True, skipMetrics)
|
||||
@ -307,8 +312,8 @@ def legacy_conversion_step1(latex_file, dpi, output_format, fg_color, bg_color,
|
||||
# Creates a new LaTeX file from the original with pages specified in
|
||||
# failed_pages, pass it through pdflatex and updates the metrics
|
||||
# from the standard legacy route
|
||||
def legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics, gs,
|
||||
gs_device, gs_ext, alpha, resolution, output_format):
|
||||
def legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics,
|
||||
use_pdftocairo, conv, gs_device, gs_ext, alpha, resolution, output_format):
|
||||
|
||||
# Search for pdflatex executable
|
||||
pdflatex = find_exe(["pdflatex"])
|
||||
@ -320,19 +325,36 @@ def legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics, gs,
|
||||
filter_pages(latex_file, pdf_latex_file, failed_pages)
|
||||
|
||||
# pdflatex call
|
||||
error_pages = []
|
||||
pdflatex_status, pdflatex_stdout = run_latex(pdflatex, pdf_latex_file)
|
||||
if pdflatex_status:
|
||||
error_pages = check_latex_log(latex_file_re.sub(".log", pdf_latex_file))
|
||||
|
||||
pdf_file = latex_file_re.sub(".pdf", pdf_latex_file)
|
||||
latex_file_root = latex_file_re.sub("", pdf_latex_file)
|
||||
|
||||
# GhostScript call to produce bitmaps
|
||||
gs_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%s"' \
|
||||
% (gs, gs_device, latex_file_re.sub("", pdf_latex_file), \
|
||||
gs_ext, alpha, alpha, resolution, pdf_file)
|
||||
gs_status, gs_stdout = run_command(gs_call)
|
||||
if gs_status:
|
||||
# Converter call to produce bitmaps
|
||||
if use_pdftocairo:
|
||||
conv_call = '%s -png -transp -r %d "%s" "%s"' \
|
||||
% (conv, resolution, pdf_file, latex_file_root)
|
||||
conv_status, conv_stdout = run_command(conv_call)
|
||||
if not conv_status:
|
||||
seqnum_re = re.compile("-([0-9]+)")
|
||||
for name in glob.glob("%s-*.png" % latex_file_root):
|
||||
match = seqnum_re.search(name)
|
||||
if match != None:
|
||||
new_name = seqnum_re.sub(str(int(match.group(1))), name)
|
||||
os.rename(name, new_name)
|
||||
else:
|
||||
conv_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%s"' \
|
||||
% (conv, gs_device, latex_file_root, \
|
||||
gs_ext, alpha, alpha, resolution, pdf_file)
|
||||
conv_status, conv_stdout = run_command(conv_call)
|
||||
|
||||
if conv_status:
|
||||
# Give up!
|
||||
warning("Some pages failed with all the possible routes")
|
||||
else:
|
||||
@ -340,6 +362,12 @@ def legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics, gs,
|
||||
pdf_log_file = latex_file_re.sub(".log", pdf_latex_file)
|
||||
pdf_metrics = legacy_extract_metrics_info(pdf_log_file)
|
||||
|
||||
# Invalidate metrics for pages that produced errors
|
||||
if len(error_pages) > 0:
|
||||
for index in error_pages:
|
||||
pdf_metrics.pop(index - 1)
|
||||
pdf_metrics.insert(index - 1, (index, -1.0))
|
||||
|
||||
original_bitmap = latex_file_re.sub("%d." + output_format, pdf_latex_file)
|
||||
destination_bitmap = latex_file_re.sub("%d." + output_format, latex_file)
|
||||
|
||||
@ -371,20 +399,33 @@ def legacy_conversion_step2(latex_file, dpi, output_format, skipMetrics = False)
|
||||
|
||||
|
||||
# Either latex and dvips have been run and we have a ps file, or
|
||||
# pdflatex has been run and we have a pdf file. Proceed with gs.
|
||||
# pdflatex has been run and we have a pdf file. Proceed with pdftocairo or gs.
|
||||
def legacy_conversion_step3(latex_file, dpi, output_format, dvips_failed, skipMetrics = False):
|
||||
# External programs used by the script.
|
||||
gs = find_exe_or_terminate(["gswin32c", "gswin64c", "gs"])
|
||||
pnmcrop = find_exe(["pnmcrop"])
|
||||
pdftocairo = find_exe(["pdftocairo"])
|
||||
epstopdf = find_exe(["epstopdf"])
|
||||
use_pdftocairo = pdftocairo != None and output_format == "png"
|
||||
if use_pdftocairo:
|
||||
conv = pdftocairo
|
||||
else:
|
||||
conv = gs
|
||||
|
||||
# Files to process
|
||||
pdf_file = latex_file_re.sub(".pdf", latex_file)
|
||||
ps_file = latex_file_re.sub(".ps", latex_file)
|
||||
|
||||
# Extract resolution data for gs from the log file.
|
||||
# The latex file name without extension
|
||||
latex_file_root = latex_file_re.sub("", latex_file)
|
||||
|
||||
# Extract resolution data for the converter from the log file.
|
||||
log_file = latex_file_re.sub(".log", latex_file)
|
||||
resolution = extract_resolution(log_file, dpi)
|
||||
|
||||
# Check whether some pages produced errors
|
||||
error_pages = check_latex_log(log_file)
|
||||
|
||||
# Older versions of gs have problems with a large degree of
|
||||
# anti-aliasing at high resolutions
|
||||
alpha = 4
|
||||
@ -406,48 +447,86 @@ def legacy_conversion_step3(latex_file, dpi, output_format, dvips_failed, skipMe
|
||||
# Generate the bitmap images
|
||||
if dvips_failed:
|
||||
# dvips failed, maybe there's a PDF, try to produce bitmaps
|
||||
gs_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%s"' \
|
||||
% (gs, gs_device, latex_file_re.sub("", latex_file), \
|
||||
gs_ext, alpha, alpha, resolution, pdf_file)
|
||||
if use_pdftocairo:
|
||||
conv_call = '%s -png -transp -r %d "%s" "%s"' \
|
||||
% (pdftocairo, resolution, pdf_file, latex_file_root)
|
||||
|
||||
gs_status, gs_stdout = run_command(gs_call)
|
||||
if gs_status:
|
||||
error("Failed: %s %s" % (os.path.basename(gs), ps_file))
|
||||
conv_status, conv_stdout = run_command(conv_call)
|
||||
if not conv_status:
|
||||
seqnum_re = re.compile("-([0-9]+)")
|
||||
for name in glob.glob("%s-*.png" % latex_file_root):
|
||||
match = seqnum_re.search(name)
|
||||
if match != None:
|
||||
new_name = seqnum_re.sub(str(int(match.group(1))), name)
|
||||
os.rename(name, new_name)
|
||||
else:
|
||||
conv_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%s"' \
|
||||
% (gs, gs_device, latex_file_root, \
|
||||
gs_ext, alpha, alpha, resolution, pdf_file)
|
||||
|
||||
conv_status, conv_stdout = run_command(conv_call)
|
||||
|
||||
if conv_status:
|
||||
error("Failed: %s %s" % (os.path.basename(conv), pdf_file))
|
||||
else:
|
||||
# Model for calling gs on each file
|
||||
gs_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%%s"' \
|
||||
% (gs, gs_device, latex_file_re.sub("", latex_file), \
|
||||
gs_ext, alpha, alpha, resolution)
|
||||
# Model for calling the converter on each file
|
||||
if use_pdftocairo and epstopdf != None:
|
||||
conv_call = '%s -png -transp -singlefile -r %d "%%s" "%s%%d"' \
|
||||
% (pdftocairo, resolution, latex_file_root)
|
||||
else:
|
||||
conv_call = '%s -dNOPAUSE -dBATCH -dSAFER -sDEVICE=%s ' \
|
||||
'-sOutputFile="%s%%d.%s" ' \
|
||||
'-dGraphicsAlphaBit=%d -dTextAlphaBits=%d ' \
|
||||
'-r%f "%%s"' \
|
||||
% (gs, gs_device, latex_file_root, \
|
||||
gs_ext, alpha, alpha, resolution)
|
||||
|
||||
i = 0
|
||||
# Collect all the PostScript files (like *.001, *.002, ...)
|
||||
ps_files = glob.glob("%s.[0-9][0-9][0-9]" % latex_file_re.sub("", latex_file))
|
||||
ps_files = glob.glob("%s.[0-9][0-9][0-9]" % latex_file_root)
|
||||
ps_files.sort()
|
||||
|
||||
# Call GhostScript for each file
|
||||
# Call the converter for each file
|
||||
for file in ps_files:
|
||||
i = i + 1
|
||||
progress("Processing page %s, file %s" % (i, file))
|
||||
gs_status, gs_stdout = run_command(gs_call % (i, file))
|
||||
if gs_status:
|
||||
# gs failed, keep track of this
|
||||
warning("Ghostscript failed on page %s, file %s" % (i, file))
|
||||
if use_pdftocairo and epstopdf != None:
|
||||
conv_name = "epstopdf"
|
||||
conv_status, conv_stdout = run_command("%s --outfile=%s.pdf %s"
|
||||
% (epstopdf, file, file))
|
||||
if not conv_status:
|
||||
conv_name = "pdftocairo"
|
||||
file = file + ".pdf"
|
||||
conv_status, conv_stdout = run_command(conv_call % (file, i))
|
||||
else:
|
||||
conv_name = "ghostscript"
|
||||
conv_status, conv_stdout = run_command(conv_call % (i, file))
|
||||
|
||||
if conv_status:
|
||||
# The converter failed, keep track of this
|
||||
warning("%s failed on page %s, file %s" % (conv_name, i, file))
|
||||
failed_pages.append(i)
|
||||
|
||||
# Pass failed pages to pdflatex
|
||||
if len(failed_pages) > 0:
|
||||
legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics, gs,
|
||||
gs_device, gs_ext, alpha, resolution, output_format)
|
||||
warning("Now trying to obtain failed previews through pdflatex")
|
||||
legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics,
|
||||
use_pdftocairo, conv, gs_device, gs_ext, alpha, resolution,
|
||||
output_format)
|
||||
|
||||
# Crop the images
|
||||
if pnmcrop != None:
|
||||
crop_files(pnmcrop, latex_file_re.sub("", latex_file))
|
||||
# Invalidate metrics for pages that produced errors
|
||||
if len(error_pages) > 0:
|
||||
for index in error_pages:
|
||||
if index not in failed_pages:
|
||||
legacy_metrics.pop(index - 1)
|
||||
legacy_metrics.insert(index - 1, (index, -1.0))
|
||||
|
||||
# Crop the ppm images
|
||||
if pnmcrop != None and output_format == "ppm":
|
||||
crop_files(pnmcrop, latex_file_root)
|
||||
|
||||
# Allow to skip .metrics creation for custom management
|
||||
# (see the dvipng method)
|
||||
|
@ -79,10 +79,11 @@ import getopt, glob, os, re, shutil, string, sys
|
||||
|
||||
from legacy_lyxpreview2ppm import legacy_conversion_step1
|
||||
|
||||
from lyxpreview_tools import bibtex_commands, copyfileobj, error, \
|
||||
filter_pages, find_exe, find_exe_or_terminate, join_metrics_and_rename, \
|
||||
latex_commands, latex_file_re, make_texcolor, mkstemp, pdflatex_commands, \
|
||||
progress, run_command, run_latex, run_tex, warning, write_metrics_info
|
||||
from lyxpreview_tools import bibtex_commands, check_latex_log, copyfileobj, \
|
||||
error, filter_pages, find_exe, find_exe_or_terminate, \
|
||||
join_metrics_and_rename, latex_commands, latex_file_re, make_texcolor, \
|
||||
mkstemp, pdflatex_commands, progress, run_command, run_latex, run_tex, \
|
||||
warning, write_metrics_info
|
||||
|
||||
|
||||
def usage(prog_name):
|
||||
@ -159,18 +160,25 @@ def extract_metrics_info(dvipng_stdout):
|
||||
|
||||
def fix_latex_file(latex_file):
|
||||
documentclass_re = re.compile("(\\\\documentclass\[)(1[012]pt,?)(.+)")
|
||||
newcommandx_re = re.compile("^(\\\\newcommandx)(.+)")
|
||||
|
||||
tmp = mkstemp()
|
||||
|
||||
changed = 0
|
||||
for line in open(latex_file, 'r').readlines():
|
||||
match = documentclass_re.match(line)
|
||||
if match != None:
|
||||
changed = 1
|
||||
tmp.write("%s%s\n" % (match.group(1), match.group(3)))
|
||||
continue
|
||||
|
||||
match = newcommandx_re.match(line)
|
||||
if match == None:
|
||||
tmp.write(line)
|
||||
continue
|
||||
|
||||
changed = 1
|
||||
tmp.write("%s%s\n" % (match.group(1), match.group(3)))
|
||||
tmp.write("\\providecommandx%s\n" % match.group(2))
|
||||
|
||||
if changed:
|
||||
copyfileobj(tmp, open(latex_file,"wb"), 1)
|
||||
@ -195,15 +203,17 @@ def convert_to_ppm_format(pngtopnm, basename):
|
||||
|
||||
# Returns a tuple of:
|
||||
# ps_pages: list of page indexes of pages containing PS literals
|
||||
# pdf_pages: list of page indexes of pages requiring running pdflatex
|
||||
# page_count: total number of pages
|
||||
# pages_parameter: parameter for dvipng to exclude pages with PostScript
|
||||
# pages_parameter: parameter for dvipng to exclude pages with PostScript/PDF
|
||||
def find_ps_pages(dvi_file):
|
||||
# latex failed
|
||||
# FIXME: try with pdflatex
|
||||
if not os.path.isfile(dvi_file):
|
||||
error("No DVI output.")
|
||||
|
||||
# Check for PostScript specials in the dvi, badly supported by dvipng
|
||||
# Check for PostScript specials in the dvi, badly supported by dvipng,
|
||||
# and inclusion of PDF/PNG/JPG files.
|
||||
# This is required for correct rendering of PSTricks and TikZ
|
||||
dv2dt = find_exe_or_terminate(["dv2dt"])
|
||||
dv2dt_call = '%s "%s"' % (dv2dt, dvi_file)
|
||||
@ -211,33 +221,53 @@ def find_ps_pages(dvi_file):
|
||||
# The output from dv2dt goes to stdout
|
||||
dv2dt_status, dv2dt_output = run_command(dv2dt_call)
|
||||
psliteral_re = re.compile("^special[1-4] [0-9]+ '(\"|ps:)")
|
||||
hyperref_re = re.compile("^special[1-4] [0-9]+ 'ps:.*/DEST pdfmark")
|
||||
pdffile_re = re.compile("^special[1-4] [0-9]+ 'PSfile=.*\\.(pdf|png|jpg|jpeg|PDF|PNG|JPG|JPEG)")
|
||||
|
||||
# Parse the dtl file looking for PostScript specials.
|
||||
# Pages using PostScript specials are recorded in ps_pages and then
|
||||
# used to create a different LaTeX file for processing in legacy mode.
|
||||
# Parse the dtl file looking for PostScript specials and pdflatex files.
|
||||
# Pages using PostScript specials or pdflatex files are recorded in
|
||||
# ps_pages or pdf_pages, respectively, and then used to create a
|
||||
# different LaTeX file for processing in legacy mode.
|
||||
# If hyperref is detected, the corresponding page is recorded in pdf_pages.
|
||||
page_has_ps = False
|
||||
page_has_pdf = False
|
||||
page_index = 0
|
||||
ps_pages = []
|
||||
pdf_pages = []
|
||||
ps_or_pdf_pages = []
|
||||
|
||||
for line in dv2dt_output.split("\n"):
|
||||
# New page
|
||||
if line.startswith("bop"):
|
||||
page_has_ps = False
|
||||
page_has_pdf = False
|
||||
page_index += 1
|
||||
|
||||
# End of page
|
||||
if line.startswith("eop") and page_has_ps:
|
||||
# We save in a list all the PostScript pages
|
||||
ps_pages.append(page_index)
|
||||
if line.startswith("eop") and (page_has_ps or page_has_pdf):
|
||||
# We save in a list all the PostScript/PDF pages
|
||||
if page_has_ps:
|
||||
ps_pages.append(page_index)
|
||||
else:
|
||||
pdf_pages.append(page_index)
|
||||
ps_or_pdf_pages.append(page_index)
|
||||
|
||||
if psliteral_re.match(line) != None:
|
||||
# Literal PostScript special detected!
|
||||
page_has_ps = True
|
||||
# If hyperref is detected, put this page on the pdf pages list
|
||||
if hyperref_re.match(line) != None:
|
||||
page_has_ps = False
|
||||
page_has_pdf = True
|
||||
else:
|
||||
page_has_ps = True
|
||||
elif pdffile_re.match(line) != None:
|
||||
# Inclusion of pdflatex image file detected!
|
||||
page_has_pdf = True
|
||||
|
||||
# Create the -pp parameter for dvipng
|
||||
pages_parameter = ""
|
||||
if len(ps_pages) > 0 and len(ps_pages) < page_index:
|
||||
# Don't process Postscript pages with dvipng by selecting the
|
||||
if len(ps_or_pdf_pages) > 0 and len(ps_or_pdf_pages) < page_index:
|
||||
# Don't process Postscript/PDF pages with dvipng by selecting the
|
||||
# wanted pages through the -pp parameter. E.g., dvipng -pp 4-12,14,64
|
||||
pages_parameter = " -pp "
|
||||
skip = True
|
||||
@ -246,7 +276,7 @@ def find_ps_pages(dvi_file):
|
||||
# Use page ranges, as a list of pages could exceed command line
|
||||
# maximum length (especially under Win32)
|
||||
for index in xrange(1, page_index + 1):
|
||||
if (not index in ps_pages) and skip:
|
||||
if (not index in ps_or_pdf_pages) and skip:
|
||||
# We were skipping pages but current page shouldn't be skipped.
|
||||
# Add this page to -pp, it could stay alone or become the
|
||||
# start of a range.
|
||||
@ -255,7 +285,7 @@ def find_ps_pages(dvi_file):
|
||||
last = index
|
||||
# We're not skipping anymore
|
||||
skip = False
|
||||
elif (index in ps_pages) and (not skip):
|
||||
elif (index in ps_or_pdf_pages) and (not skip):
|
||||
# We weren't skipping but current page should be skipped
|
||||
if last != index - 1:
|
||||
# If the start index of the range is the previous page
|
||||
@ -270,10 +300,10 @@ def find_ps_pages(dvi_file):
|
||||
# Remove the trailing separator
|
||||
pages_parameter = pages_parameter.rstrip(",")
|
||||
# We've to manage the case in which the last page is closing a range
|
||||
if (not index in ps_pages) and (not skip) and (last != index):
|
||||
if (not index in ps_or_pdf_pages) and (not skip) and (last != index):
|
||||
pages_parameter += "-" + str(index)
|
||||
|
||||
return (ps_pages, page_index, pages_parameter)
|
||||
return (ps_pages, pdf_pages, page_index, pages_parameter)
|
||||
|
||||
def main(argv):
|
||||
# Set defaults.
|
||||
@ -368,7 +398,8 @@ def main(argv):
|
||||
progress("Preprocess through lilypond-book: %s" % lilypond)
|
||||
progress("Altering the latex file for font size and colors")
|
||||
|
||||
# Omit font size specification in latex file.
|
||||
# Omit font size specification in latex file and make sure multiple
|
||||
# defined macros are not an issue.
|
||||
fix_latex_file(latex_file)
|
||||
|
||||
if lilypond:
|
||||
@ -411,9 +442,11 @@ def main(argv):
|
||||
fg_color, bg_color, latex, pdf_output)
|
||||
|
||||
# Compile the latex file.
|
||||
error_pages = []
|
||||
latex_status, latex_stdout = run_latex(latex, latex_file, bibtex)
|
||||
if latex_status:
|
||||
return (latex_status, [])
|
||||
warning("trying to recover from failed compilation")
|
||||
error_pages = check_latex_log(latex_file_re.sub(".log", latex_file))
|
||||
|
||||
# The dvi output file name
|
||||
dvi_file = latex_file_re.sub(".dvi", latex_file)
|
||||
@ -432,17 +465,22 @@ def main(argv):
|
||||
error("No DVI or PDF output. %s failed." \
|
||||
% (os.path.basename(latex)))
|
||||
|
||||
# Look for PS literals in DVI pages
|
||||
# ps_pages: list of page indexes of pages containing PS literals
|
||||
# Look for PS literals or inclusion of pdflatex files in DVI pages
|
||||
# ps_pages: list of indexes of pages containing PS literals
|
||||
# pdf_pages: list of indexes of pages requiring running pdflatex
|
||||
# page_count: total number of pages
|
||||
# pages_parameter: parameter for dvipng to exclude pages with PostScript
|
||||
(ps_pages, page_count, pages_parameter) = find_ps_pages(dvi_file)
|
||||
(ps_pages, pdf_pages, page_count, pages_parameter) = find_ps_pages(dvi_file)
|
||||
|
||||
# If all pages need PostScript, directly use the legacy method.
|
||||
# If all pages need PostScript or pdflatex, directly use the legacy method.
|
||||
if len(ps_pages) == page_count:
|
||||
progress("Using the legacy conversion method (PostScript support)")
|
||||
return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
|
||||
bg_color, latex, pdf_output)
|
||||
elif len(pdf_pages) == page_count:
|
||||
progress("Using the legacy conversion method (PDF support)")
|
||||
return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
|
||||
bg_color, "pdflatex", True)
|
||||
|
||||
# Run the dvi file through dvipng.
|
||||
dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" %s "%s"' \
|
||||
@ -481,6 +519,34 @@ def main(argv):
|
||||
join_metrics_and_rename(dvipng_metrics, legacy_metrics, ps_pages,
|
||||
original_bitmap, destination_bitmap)
|
||||
|
||||
# If some pages require running pdflatex pass them to legacy method
|
||||
if len(pdf_pages) > 0:
|
||||
# Create a new LaTeX file just for the snippets needing
|
||||
# the legacy method
|
||||
legacy_latex_file = latex_file_re.sub("_legacy.tex", latex_file)
|
||||
filter_pages(latex_file, legacy_latex_file, pdf_pages)
|
||||
|
||||
# Pass the new LaTeX file to the legacy method
|
||||
progress("Pages %s require processing with pdflatex" % pdf_pages)
|
||||
progress("Using the legacy conversion method (PDF support)")
|
||||
legacy_status, legacy_metrics = legacy_conversion_step1(legacy_latex_file,
|
||||
dpi, output_format, fg_color, bg_color, "pdflatex", True, True)
|
||||
|
||||
# Now we need to mix metrics data from dvipng and the legacy method
|
||||
original_bitmap = latex_file_re.sub("%d." + output_format, legacy_latex_file)
|
||||
destination_bitmap = latex_file_re.sub("%d." + output_format, latex_file)
|
||||
|
||||
# Join metrics from dvipng and legacy, and rename legacy bitmaps
|
||||
join_metrics_and_rename(dvipng_metrics, legacy_metrics, pdf_pages,
|
||||
original_bitmap, destination_bitmap)
|
||||
|
||||
# Invalidate metrics for pages that produced errors
|
||||
if len(error_pages) > 0:
|
||||
for index in error_pages:
|
||||
if index not in ps_pages and index not in pdf_pages:
|
||||
dvipng_metrics.pop(index - 1)
|
||||
dvipng_metrics.insert(index - 1, (index, -1.0))
|
||||
|
||||
# Convert images to ppm format if necessary.
|
||||
if output_format == "ppm":
|
||||
convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file))
|
||||
|
@ -363,3 +363,39 @@ def string_in_file(string, infile):
|
||||
return True
|
||||
f.close()
|
||||
return False
|
||||
|
||||
|
||||
# Returns a list of indexes of pages giving errors extracted from the latex log
|
||||
def check_latex_log(log_file):
|
||||
|
||||
error_re = re.compile("^! ")
|
||||
snippet_re = re.compile("^Preview: Snippet ")
|
||||
data_re = re.compile("([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)")
|
||||
|
||||
found_error = False
|
||||
error_pages = []
|
||||
|
||||
try:
|
||||
for line in open(log_file, 'r').readlines():
|
||||
if not found_error:
|
||||
match = error_re.match(line)
|
||||
if match != None:
|
||||
found_error = True
|
||||
continue
|
||||
else:
|
||||
match = snippet_re.match(line)
|
||||
if match == None:
|
||||
continue
|
||||
|
||||
found_error = False
|
||||
match = data_re.search(line)
|
||||
if match == None:
|
||||
error("Unexpected data in %s\n%s" % (log_file, line))
|
||||
|
||||
error_pages.append(int(match.group(1)))
|
||||
|
||||
except:
|
||||
warning('check_latex_log: Unable to open "%s"' % log_file)
|
||||
warning(`sys.exc_type` + ',' + `sys.exc_value`)
|
||||
|
||||
return error_pages
|
||||
|
Loading…
Reference in New Issue
Block a user