X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Fscripts%2Flyxpreview2bitmap.py;h=ac425f14d272a6aea3df419f8917769224d3da7a;hb=76ffbd136ae935861e8b98a9e47b3ad0957924be;hp=d7802edf70844ecc888e7321ee2637ed9ca2048b;hpb=10759f21126550c81bcee3606768038fdbe758c7;p=lyx.git diff --git a/lib/scripts/lyxpreview2bitmap.py b/lib/scripts/lyxpreview2bitmap.py index d7802edf70..ac425f14d2 100755 --- a/lib/scripts/lyxpreview2bitmap.py +++ b/lib/scripts/lyxpreview2bitmap.py @@ -1,5 +1,5 @@ #! /usr/bin/env python -# -*- coding: iso-8859-1 -*- +# -*- coding: utf-8 -*- # file lyxpreview2bitmap.py # This file is part of LyX, the document processor. @@ -8,7 +8,7 @@ # author Angus Leeming # with much advice from members of the preview-latex project: # David Kastrup, dak@gnu.org and -# Jan-Åke Larsson, jalar@mai.liu.se. +# Jan-Åke Larsson, jalar@mai.liu.se. # Full author contact details are available in file CREDITS @@ -30,12 +30,14 @@ # Example usage: # lyxpreview2bitmap.py png 0lyxpreview.tex 128 000000 faf0e6 -# This script takes five arguments: -# FORMAT: either 'png' or 'ppm'. The desired output format. +# This script takes six arguments: +# FORMAT: The desired output format. Either 'png' or 'ppm'. # TEXFILE: the name of the .tex file to be converted. -# DPI: a scale factor, passed to dvipng. +# DPI: a scale factor, used to ascertain the resolution of the +# generated image which is then passed to gs. # FG_COLOR: the foreground color as a hexadecimal string, eg '000000'. # BG_COLOR: the background color as a hexadecimal string, eg 'faf0e6'. +# CONVERTER: the converter (optional). Default is latex. # Decomposing TEXFILE's name as DIR/BASE.tex, this script will, # if executed successfully, leave in DIR: @@ -45,84 +47,92 @@ # the images correctly on the screen. import glob, os, re, string, sys -from legacy_lyxpreview2ppm import legacy_conversion + +from legacy_lyxpreview2ppm import legacy_conversion, \ + legacy_conversion_step2 + +from lyxpreview_tools import copyfileobj, error, find_exe, \ + find_exe_or_terminate, make_texcolor, mkstemp, run_command, warning # Pre-compiled regular expressions. -hexcolor_re = re.compile("^[0-9a-fA-F]{6}$") latex_file_re = re.compile("\.tex$") def usage(prog_name): - return "Usage: %s \n"\ + return "Usage: %s \n"\ "\twhere the colors are hexadecimal strings, eg 'faf0e6'"\ % prog_name -def error(message): - sys.stderr.write(message + '\n') - sys.exit(1) - - -def find_exe(candidates, path): - for prog in candidates: - for directory in path: - full_path = os.path.join(directory, prog) - if os.access(full_path, os.X_OK): - return full_path - - return None - - -def find_exe_or_terminate(candidates, path): - exe = find_exe(candidates, path) - if exe == None: - error("Unable to find executable from '%s'" % string.join(candidates)) - - return exe - - -def run_command(cmd): - handle = os.popen(cmd, 'r') - cmd_stdout = handle.read() - cmd_status = handle.close() - - return cmd_status, cmd_stdout - - -def make_texcolor(hexcolor): - # Test that the input string contains 6 hexadecimal chars. - if not hexcolor_re.match(hexcolor): - error("Cannot convert color '%s'" % hexcolor) - - red = float(string.atoi(hexcolor[0:2], 16)) / 255.0 - green = float(string.atoi(hexcolor[2:4], 16)) / 255.0 - blue = float(string.atoi(hexcolor[4:6], 16)) / 255.0 - - return "rgb %f %f %f" % (red, green, blue) - - def extract_metrics_info(dvipng_stdout, metrics_file): metrics = open(metrics_file, 'w') - metrics_re = re.compile("\[([0-9]+) depth=(-?[0-9]+) height=(-?[0-9]+)") +# "\[[0-9]+" can match two kinds of numbers: page numbers from dvipng +# and glyph numbers from mktexpk. The glyph numbers always match +# "\[[0-9]+\]" while the page number never is followed by "\]". Thus: + page_re = re.compile("\[([0-9]+)[^]]"); + metrics_re = re.compile("depth=(-?[0-9]+) height=(-?[0-9]+)") success = 0 + page = "" pos = 0 while 1: + match = page_re.search(dvipng_stdout, pos) + if match == None: + break + page = match.group(1) + pos = match.end() match = metrics_re.search(dvipng_stdout, pos) if match == None: break success = 1 # Calculate the 'ascent fraction'. - descent = string.atof(match.group(2)) - ascent = string.atof(match.group(3)) + descent = string.atof(match.group(1)) + ascent = string.atof(match.group(2)) + frac = 0.5 - if abs(ascent + descent) > 0.1: - frac = ascent / (ascent + descent) + if ascent >= 0 or descent >= 0: + if abs(ascent + descent) > 0.1: + frac = ascent / (ascent + descent) + + # Sanity check + if frac < 0: + frac = 0.5 + + metrics.write("Snippet %s %f\n" % (page, frac)) + pos = match.end() + 2 + + return success - metrics.write("Snippet %s %f\n" % (match.group(1), frac)) - pos = match.end(3) + 2 + +def color_pdf(latex_file, bg_color): + use_preview_pdf_re = re.compile("(\s*\\\\usepackage\[[^]]+)(pdftex\]{preview})") + + tmp = mkstemp() + + success = 0 + try: + for line in open(latex_file, 'r').readlines(): + match = use_preview_pdf_re.match(line) + if match == None: + tmp.write(line) + continue + success = 1 + tmp.write(" \\usepackage{color}\n" \ + " \\pagecolor[rgb]{%s}\n" \ + "%s\n" \ + % (bg_color, match.group())) + continue + + except: + # Unable to open the file, but do nothing here because + # the calling function will act on the value of 'success'. + warning('Warning in color_pdf! Unable to open "%s"' % latex_file) + warning(`sys.exc_type` + ',' + `sys.exc_value`) + + if success: + copyfileobj(tmp, open(latex_file,"wb"), 1) return success @@ -133,7 +143,7 @@ def convert_to_ppm_format(pngtopnm, basename): for png_file in glob.glob("%s*.png" % basename): ppm_file = png_file_re.sub(".ppm", png_file) - p2p_cmd = "%s %s" % (pngtopnm, png_file) + p2p_cmd = '%s "%s"' % (pngtopnm, png_file) p2p_status, p2p_stdout = run_command(p2p_cmd) if p2p_status != None: error("Unable to convert %s to ppm format" % png_file) @@ -145,7 +155,7 @@ def convert_to_ppm_format(pngtopnm, basename): def main(argv): # Parse and manipulate the command line arguments. - if len(argv) != 6: + if len(argv) != 6 and len(argv) != 7: error(usage(argv[0])) output_format = string.lower(argv[1]) @@ -155,43 +165,59 @@ def main(argv): os.chdir(dir) dpi = string.atoi(argv[3]) - fg_color = make_texcolor(argv[4]) - bg_color = make_texcolor(argv[5]) + fg_color = make_texcolor(argv[4], False) + bg_color = make_texcolor(argv[5], False) + + bg_color_gr = make_texcolor(argv[5], True) # External programs used by the script. - path = string.split(os.getenv("PATH"), os.pathsep) - latex = find_exe_or_terminate(["pplatex", "latex2e", "latex"], path) + path = string.split(os.environ["PATH"], os.pathsep) + if len(argv) == 7: + latex = argv[6] + else: + latex = find_exe_or_terminate(["latex", "pplatex", "platex", "latex2e"], path) # This can go once dvipng becomes widespread. dvipng = find_exe(["dvipng"], path) if dvipng == None: - if output_format == "ppm": - return legacy_conversion(argv) - else: - error("The old 'dvi->ps->ppm' conversion requires " - "ppm as the output format") + # The data is input to legacy_conversion in as similar + # as possible a manner to that input to the code used in + # LyX 1.3.x. + vec = [ argv[0], argv[2], argv[3], argv[1], argv[4], argv[5], latex ] + return legacy_conversion(vec) pngtopnm = "" if output_format == "ppm": pngtopnm = find_exe_or_terminate(["pngtopnm"], path) + # Move color information for PDF into the latex file. + if not color_pdf(latex_file, bg_color_gr): + error("Unable to move color info into the latex file") + # Compile the latex file. - latex_call = "%s %s" % (latex, latex_file) + latex_call = '%s "%s"' % (latex, latex_file) latex_status, latex_stdout = run_command(latex_call) if latex_status != None: - error("%s failed to compile %s" \ + warning("%s failed to compile %s" \ % (os.path.basename(latex), latex_file)) + if latex == "xelatex": + warning("Using XeTeX") + # FIXME: skip unnecessary dvips trial in legacy_conversion_step2 + return legacy_conversion_step2(latex_file, dpi, output_format) + # Run the dvi file through dvipng. dvi_file = latex_file_re.sub(".dvi", latex_file) - dvipng_call = "%s -Ttight -depth -height -D %d -fg '%s' -bg '%s' %s" \ + dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" "%s"' \ % (dvipng, dpi, fg_color, bg_color, dvi_file) dvipng_status, dvipng_stdout = run_command(dvipng_call) if dvipng_status != None: - error("%s failed to generate images from %s" \ + warning("%s failed to generate images from %s ... looking for PDF" \ % (os.path.basename(dvipng), dvi_file)) + # FIXME: skip unnecessary dvips trial in legacy_conversion_step2 + return legacy_conversion_step2(latex_file, dpi, output_format) # Extract metrics info from dvipng_stdout. metrics_file = latex_file_re.sub(".metrics", latex_file) @@ -204,5 +230,6 @@ def main(argv): return 0 + if __name__ == "__main__": main(sys.argv)