Try even harder to obtain an instant preview

This is a followup commit to 691fdea3 and restores the behavior of the
script as it was intended before 64e0c558, other than taking into account
possible inclusion of files that only pdflatex can process and the
possibility of multiple defined math macros.
The instant previews in the math manual now work again.
This commit is contained in:
Enrico Forestieri 2015-04-29 12:28:51 +02:00
parent ec7833272a
commit 75f7eafd65
2 changed files with 74 additions and 27 deletions

View File

@ -482,13 +482,13 @@ def legacy_conversion_step3(latex_file, dpi, output_format, dvips_failed, skipMe
i = i + 1 i = i + 1
progress("Processing page %s, file %s" % (i, file)) progress("Processing page %s, file %s" % (i, file))
if use_pdftocairo and epstopdf != None: if use_pdftocairo and epstopdf != None:
conv_name = "PdfToCairo" conv_name = "pdftocairo"
conv_status, conv_stdout = run_command("%s --outfile=%s.pdf %s" conv_status, conv_stdout = run_command("%s --outfile=%s.pdf %s"
% (epstopdf, file, file)) % (epstopdf, file, file))
if not conv_status: if not conv_status:
conv_status, conv_stdout = run_command(conv_call % (file, i)) conv_status, conv_stdout = run_command(conv_call % (file, i))
else: else:
conv_name = "Ghostscript" conv_name = "ghostscript"
conv_status, conv_stdout = run_command(conv_call % (i, file)) conv_status, conv_stdout = run_command(conv_call % (i, file))
if conv_status: if conv_status:
@ -498,6 +498,7 @@ def legacy_conversion_step3(latex_file, dpi, output_format, dvips_failed, skipMe
# Pass failed pages to pdflatex # Pass failed pages to pdflatex
if len(failed_pages) > 0: if len(failed_pages) > 0:
warning("Now trying to obtain failed previews through pdflatex")
legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics, legacy_conversion_pdflatex(latex_file, failed_pages, legacy_metrics,
use_pdftocairo, conv, gs_device, gs_ext, alpha, resolution, use_pdftocairo, conv, gs_device, gs_ext, alpha, resolution,
output_format) output_format)

View File

@ -159,18 +159,25 @@ def extract_metrics_info(dvipng_stdout):
def fix_latex_file(latex_file): def fix_latex_file(latex_file):
documentclass_re = re.compile("(\\\\documentclass\[)(1[012]pt,?)(.+)") documentclass_re = re.compile("(\\\\documentclass\[)(1[012]pt,?)(.+)")
newcommandx_re = re.compile("^(\\\\newcommandx)(.+)")
tmp = mkstemp() tmp = mkstemp()
changed = 0 changed = 0
for line in open(latex_file, 'r').readlines(): for line in open(latex_file, 'r').readlines():
match = documentclass_re.match(line) 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: if match == None:
tmp.write(line) tmp.write(line)
continue continue
changed = 1 changed = 1
tmp.write("%s%s\n" % (match.group(1), match.group(3))) tmp.write("\\providecommandx%s\n" % match.group(2))
if changed: if changed:
copyfileobj(tmp, open(latex_file,"wb"), 1) copyfileobj(tmp, open(latex_file,"wb"), 1)
@ -195,15 +202,17 @@ def convert_to_ppm_format(pngtopnm, basename):
# Returns a tuple of: # Returns a tuple of:
# ps_pages: list of page indexes of pages containing PS literals # 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 # 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): def find_ps_pages(dvi_file):
# latex failed # latex failed
# FIXME: try with pdflatex # FIXME: try with pdflatex
if not os.path.isfile(dvi_file): if not os.path.isfile(dvi_file):
error("No DVI output.") 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 # This is required for correct rendering of PSTricks and TikZ
dv2dt = find_exe_or_terminate(["dv2dt"]) dv2dt = find_exe_or_terminate(["dv2dt"])
dv2dt_call = '%s "%s"' % (dv2dt, dvi_file) dv2dt_call = '%s "%s"' % (dv2dt, dvi_file)
@ -211,33 +220,47 @@ def find_ps_pages(dvi_file):
# The output from dv2dt goes to stdout # The output from dv2dt goes to stdout
dv2dt_status, dv2dt_output = run_command(dv2dt_call) dv2dt_status, dv2dt_output = run_command(dv2dt_call)
psliteral_re = re.compile("^special[1-4] [0-9]+ '(\"|ps:)") psliteral_re = re.compile("^special[1-4] [0-9]+ '(\"|ps:)")
pdffile_re = re.compile("^special[1-4] [0-9]+ 'PSfile=.*.(pdf|png|jpg)")
# Parse the dtl file looking for PostScript specials. # Parse the dtl file looking for PostScript specials and pdflatex files.
# Pages using PostScript specials are recorded in ps_pages and then # Pages using PostScript specials or pdflatex files are recorded in
# used to create a different LaTeX file for processing in legacy mode. # ps_pages or pdf_pages, respectively, and then used to create a
# different LaTeX file for processing in legacy mode.
page_has_ps = False page_has_ps = False
page_has_pdf = False
page_index = 0 page_index = 0
ps_pages = [] ps_pages = []
pdf_pages = []
ps_or_pdf_pages = []
for line in dv2dt_output.split("\n"): for line in dv2dt_output.split("\n"):
# New page # New page
if line.startswith("bop"): if line.startswith("bop"):
page_has_ps = False page_has_ps = False
page_has_pdf = False
page_index += 1 page_index += 1
# End of page # End of page
if line.startswith("eop") and page_has_ps: if line.startswith("eop") and (page_has_ps or page_has_pdf):
# We save in a list all the PostScript pages # We save in a list all the PostScript/PDF pages
ps_pages.append(page_index) 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: if psliteral_re.match(line) != None:
# Literal PostScript special detected! # Literal PostScript special detected!
page_has_ps = True page_has_ps = True
if pdffile_re.match(line) != None:
# Inclusion of pdflatex image file detected!
page_has_pdf = True
# Create the -pp parameter for dvipng # Create the -pp parameter for dvipng
pages_parameter = "" pages_parameter = ""
if len(ps_pages) > 0 and len(ps_pages) < page_index: if len(ps_or_pdf_pages) > 0 and len(ps_or_pdf_pages) < page_index:
# Don't process Postscript pages with dvipng by selecting the # 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 # wanted pages through the -pp parameter. E.g., dvipng -pp 4-12,14,64
pages_parameter = " -pp " pages_parameter = " -pp "
skip = True skip = True
@ -246,7 +269,7 @@ def find_ps_pages(dvi_file):
# Use page ranges, as a list of pages could exceed command line # Use page ranges, as a list of pages could exceed command line
# maximum length (especially under Win32) # maximum length (especially under Win32)
for index in xrange(1, page_index + 1): 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. # We were skipping pages but current page shouldn't be skipped.
# Add this page to -pp, it could stay alone or become the # Add this page to -pp, it could stay alone or become the
# start of a range. # start of a range.
@ -255,7 +278,7 @@ def find_ps_pages(dvi_file):
last = index last = index
# We're not skipping anymore # We're not skipping anymore
skip = False 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 # We weren't skipping but current page should be skipped
if last != index - 1: if last != index - 1:
# If the start index of the range is the previous page # If the start index of the range is the previous page
@ -270,10 +293,10 @@ def find_ps_pages(dvi_file):
# Remove the trailing separator # Remove the trailing separator
pages_parameter = pages_parameter.rstrip(",") pages_parameter = pages_parameter.rstrip(",")
# We've to manage the case in which the last page is closing a range # 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) pages_parameter += "-" + str(index)
return (ps_pages, page_index, pages_parameter) return (ps_pages, pdf_pages, page_index, pages_parameter)
def main(argv): def main(argv):
# Set defaults. # Set defaults.
@ -368,7 +391,8 @@ def main(argv):
progress("Preprocess through lilypond-book: %s" % lilypond) progress("Preprocess through lilypond-book: %s" % lilypond)
progress("Altering the latex file for font size and colors") 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) fix_latex_file(latex_file)
if lilypond: if lilypond:
@ -411,11 +435,7 @@ def main(argv):
fg_color, bg_color, latex, pdf_output) fg_color, bg_color, latex, pdf_output)
# Compile the latex file. # Compile the latex file.
latex_status, latex_stdout = run_latex(latex, latex_file, bibtex) run_latex(latex, latex_file, bibtex)
if latex_status:
progress("Using the legacy conversion method and pdflatex (latex failed)")
return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
bg_color, "pdflatex", True)
# The dvi output file name # The dvi output file name
dvi_file = latex_file_re.sub(".dvi", latex_file) dvi_file = latex_file_re.sub(".dvi", latex_file)
@ -434,17 +454,22 @@ def main(argv):
error("No DVI or PDF output. %s failed." \ error("No DVI or PDF output. %s failed." \
% (os.path.basename(latex))) % (os.path.basename(latex)))
# Look for PS literals in DVI pages # Look for PS literals or inclusion of pdflatex files in DVI pages
# ps_pages: list of page indexes of pages containing PS literals # 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 # 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
(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: if len(ps_pages) == page_count:
progress("Using the legacy conversion method (PostScript support)") progress("Using the legacy conversion method (PostScript support)")
return legacy_conversion_step1(latex_file, dpi, output_format, fg_color, return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
bg_color, latex, pdf_output) 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. # Run the dvi file through dvipng.
dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" %s "%s"' \ dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" %s "%s"' \
@ -483,6 +508,27 @@ def main(argv):
join_metrics_and_rename(dvipng_metrics, legacy_metrics, ps_pages, join_metrics_and_rename(dvipng_metrics, legacy_metrics, ps_pages,
original_bitmap, destination_bitmap) 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 include pdflatex image files" % 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)
# Convert images to ppm format if necessary. # Convert images to ppm format if necessary.
if output_format == "ppm": if output_format == "ppm":
convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file)) convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file))