def legacy_conversion_step1(latex_file,
                            dpi,
                            output_format,
                            fg_color,
                            bg_color,
                            latex,
                            pdf_output=False,
                            skipMetrics=False):

    # Move color information, lyx and tightpage options into the latex file.
    if not legacy_latex_file(latex_file, fg_color, bg_color):
        error(
            """Unable to move the color information, and the lyx and tightpage
            options of preview-latex, into the latex file""")

    # Compile the latex file.
    latex_status, latex_stdout = run_latex(latex, latex_file)
    if latex_status:
        progress("Will try to recover from %s failure" % latex)

    if pdf_output:
        return legacy_conversion_step3(latex_file, dpi, output_format, True,
                                       skipMetrics)
    else:
        return legacy_conversion_step2(latex_file, dpi, output_format,
                                       skipMetrics)
Esempio n. 2
0
def legacy_conversion_step1(latex_file, dpi, output_format, fg_color, bg_color,
                            latex, pdf_output = False, skipMetrics = False):

    # Move color information, lyx and tightpage options into the latex file.
    if not legacy_latex_file(latex_file, fg_color, bg_color):
        error("""Unable to move the color information, and the lyx and tightpage
            options of preview-latex, into the latex file""")

    # Compile the latex file.
    latex_status, latex_stdout = run_latex(latex, latex_file)
    if latex_status:
        progress("Will try to recover from %s failure" % latex)

    if pdf_output:
        return legacy_conversion_step3(latex_file, dpi, output_format, True, skipMetrics)
    else:
        return legacy_conversion_step2(latex_file, dpi, output_format, skipMetrics)
Esempio n. 3
0
        elif opt in ("--png", "--ppm"):
            output_format = opt[2:]
        elif opt in ("-v", "--verbose"):
            import lyxpreview_tools
            lyxpreview_tools.verbose = True

    # Determine input file
    if len(args) != 1:
        err = "A single input file is required, %s given" % (len(args) or "none")
        error("%s\n%s" % (err, usage(script_name)))

    input_path = args[0]
    dir, latex_file = os.path.split(input_path)

    # Echo the settings
    progress("Starting %s..." % script_name)
    progress("Output format: %s" % output_format)
    progress("Foreground color: %s" % fg_color)
    progress("Background color: %s" % bg_color)
    progress("Resolution (dpi): %s" % dpi)
    progress("File to process: %s" % input_path)

    # Check for the input file
    if not os.path.exists(input_path):
        error('File "%s" not found.' % input_path)
    if len(dir) != 0:
        os.chdir(dir)

    fg_color_dvipng = make_texcolor(fg_color, False)
    bg_color_dvipng = make_texcolor(bg_color, False)
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"])

    # 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.
    log_file = latex_file_re.sub(".log", latex_file)
    resolution = extract_resolution(log_file, dpi)

    # Older versions of gs have problems with a large degree of
    # anti-aliasing at high resolutions
    alpha = 4
    if resolution > 150:
        alpha = 2

    gs_device = "png16m"
    gs_ext = "png"
    if output_format == "ppm":
        gs_device = "pnmraw"
        gs_ext = "ppm"

    # Extract the metrics from the log file
    legacy_metrics = legacy_extract_metrics_info(log_file)

    # List of pages which failed to produce a correct output
    failed_pages = []

    # 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)

        gs_status, gs_stdout = run_command(gs_call)
        if gs_status:
            error("Failed: %s %s" % (os.path.basename(gs), ps_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)

        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.sort()

        # Call GhostScript 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))
                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)

    # Crop the images
    if pnmcrop != None:
        crop_files(pnmcrop, latex_file_re.sub("", latex_file))

    # Allow to skip .metrics creation for custom management
    # (see the dvipng method)
    if not skipMetrics:
        # Extract metrics info from the log file.
        metrics_file = latex_file_re.sub(".metrics", latex_file)
        write_metrics_info(legacy_metrics, metrics_file)

    return (0, legacy_metrics)
Esempio n. 5
0
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)

    # 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
    if resolution > 150:
        alpha = 2

    gs_device = "png16m"
    gs_ext = "png"
    if output_format == "ppm":
        gs_device = "pnmraw"
        gs_ext = "ppm"

    # Extract the metrics from the log file
    legacy_metrics = legacy_extract_metrics_info(log_file)

    # List of pages which failed to produce a correct output
    failed_pages = []

    # Generate the bitmap images
    if dvips_failed:
        # dvips failed, maybe there's a PDF, try to produce bitmaps
        if use_pdftocairo:
            conv_call = '%s -png -transp -r %d "%s" "%s"' \
                        % (pdftocairo, 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"' \
                      % (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 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_root)
        ps_files.sort()

        # Call the converter for each file
        for file in ps_files:
            i = i + 1
            progress("Processing 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:
        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)

    # 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)
    if not skipMetrics:
        # Extract metrics info from the log file.
        metrics_file = latex_file_re.sub(".metrics", latex_file)
        write_metrics_info(legacy_metrics, metrics_file)

    return (0, legacy_metrics)
Esempio n. 6
0
def main(argv):
    # Set defaults.
    dpi = 128
    fg_color = "000000"
    bg_color = "ffffff"
    bibtex = None
    latex = None
    lilypond = False
    lilypond_book = None
    output_format = "png"
    script_name = argv[0]

    # Parse and manipulate the command line arguments.
    try:
        (opts, args) = getopt.gnu_getopt(argv[1:], "dhv", ["bibtex=", "bg=",
            "debug", "dpi=", "fg=", "help", "latex=", "lilypond",
            "lilypond-book=", "png", "ppm", "verbose"])
    except getopt.GetoptError as err:
        error("%s\n%s" % (err, usage(script_name)))

    opts.reverse()
    for opt, val in opts:
        if opt in ("-h", "--help"):
            print(usage(script_name))
            sys.exit(0)
        elif opt == "--bibtex":
            bibtex = [val]
        elif opt == "--bg":
            bg_color = val
        elif opt in ("-d", "--debug"):
            import lyxpreview_tools
            lyxpreview_tools.debug = True
        elif opt == "--dpi":
            try:
                dpi = int(val)
            except:
                error("Cannot convert %s to an integer value" % val)
        elif opt == "--fg":
            fg_color = val
        elif opt == "--latex":
            latex = [val]
        elif opt == "--lilypond":
            lilypond = True
        elif opt == "--lilypond-book":
            lilypond_book = [val]
        elif opt in ("--png", "--ppm"):
            output_format = opt[2:]
        elif opt in ("-v", "--verbose"):
            import lyxpreview_tools
            lyxpreview_tools.verbose = True

    # Determine input file
    if len(args) != 1:
        err = "A single input file is required, %s given" % (len(args) or "none")
        error("%s\n%s" % (err, usage(script_name)))

    input_path = args[0]
    dir, latex_file = os.path.split(input_path)

    # Check for the input file
    if not os.path.exists(input_path):
        error('File "%s" not found.' % input_path)
    if len(dir) != 0:
        os.chdir(dir)

    if lyxpreview_tools.verbose:
        f_out = open('debug.txt', 'a')
        sys.stdout = f_out
        sys.stderr = f_out

    # Echo the settings
    progress("Running Python %s" % str(sys.version_info[:3]))
    progress("Starting %s..." % script_name)
    if os.name == "nt":
        progress("Use win32_modules: %d" % lyxpreview_tools.use_win32_modules)
    progress("Output format: %s" % output_format)
    progress("Foreground color: %s" % fg_color)
    progress("Background color: %s" % bg_color)
    progress("Resolution (dpi): %s" % dpi)
    progress("File to process: %s" % input_path)

    # For python > 2 convert strings to bytes
    if not PY2:
        fg_color = bytes(fg_color, 'ascii')
        bg_color = bytes(bg_color, 'ascii')

    fg_color_dvipng = make_texcolor(fg_color, False)
    bg_color_dvipng = make_texcolor(bg_color, False)

    # For python > 2 convert bytes to string
    if not PY2:
        fg_color_dvipng = fg_color_dvipng.decode('ascii')
        bg_color_dvipng = bg_color_dvipng.decode('ascii')

    # External programs used by the script.
    latex = find_exe_or_terminate(latex or latex_commands)
    bibtex = find_exe(bibtex or bibtex_commands)
    if lilypond:
        lilypond_book = find_exe_or_terminate(lilypond_book or
            ["lilypond-book --safe"])

    # These flavors of latex are known to produce pdf output
    pdf_output = latex in pdflatex_commands

    progress("Latex command: %s" % latex)
    progress("Latex produces pdf output: %s" % pdf_output)
    progress("Bibtex command: %s" % bibtex)
    progress("Lilypond-book command: %s" % lilypond_book)
    progress("Preprocess through lilypond-book: %s" % lilypond)
    progress("Altering the latex file for font size and colors")

    # Make sure that multiple defined macros and the microtype package
    # don't cause issues in the latex file.
    fix_latex_file(latex_file, pdf_output)

    if lilypond:
        progress("Preprocess the latex file through %s" % lilypond_book)
        if pdf_output:
            lilypond_book += " --pdf"
        lilypond_book += " --latex-program=%s" % latex.split()[0]

        # Make a copy of the latex file
        lytex_file = latex_file_re.sub(".lytex", latex_file)
        shutil.copyfile(latex_file, lytex_file)

        # Preprocess the latex file through lilypond-book.
        lytex_status, lytex_stdout = run_tex(lilypond_book, lytex_file)

    if pdf_output:
        progress("Using the legacy conversion method (PDF support)")
        return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
            bg_color, latex, pdf_output)

    # This can go once dvipng becomes widespread.
    dvipng = find_exe(["dvipng"])
    if dvipng == None:
        progress("Using the legacy conversion method (dvipng not found)")
        return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
            bg_color, latex, pdf_output)

    dv2dt = find_exe(["dv2dt"])
    if dv2dt == None:
        progress("Using the legacy conversion method (dv2dt not found)")
        return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
            bg_color, latex, pdf_output)

    pngtopnm = ""
    if output_format == "ppm":
        pngtopnm = find_exe(["pngtopnm"])
        if pngtopnm == None:
            progress("Using the legacy conversion method (pngtopnm not found)")
            return legacy_conversion_step1(latex_file, dpi, output_format,
                fg_color, bg_color, latex, pdf_output)

    # Compile the latex file.
    error_pages = []
    latex_status, latex_stdout = run_latex(latex, latex_file, bibtex)
    latex_log = latex_file_re.sub(".log", latex_file)
    if latex_status:
        progress("Will try to recover from %s failure" % latex)
        error_pages = check_latex_log(latex_log)

    # The dvi output file name
    dvi_file = latex_file_re.sub(".dvi", latex_file)

    # If there's no DVI output, look for PDF and go to legacy or fail
    if not os.path.isfile(dvi_file):
        # No DVI, is there a PDF?
        pdf_file = latex_file_re.sub(".pdf", latex_file)
        if os.path.isfile(pdf_file):
            progress("%s produced a PDF output, fallback to legacy." \
                % (os.path.basename(latex)))
            progress("Using the legacy conversion method (PDF support)")
            return legacy_conversion_step1(latex_file, dpi, output_format,
                fg_color, bg_color, latex, True)
        else:
            error("No DVI or PDF output. %s failed." \
                % (os.path.basename(latex)))

    # 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, pdf_pages, page_count, pages_parameter) = find_ps_pages(dvi_file)

    # 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)

    # Retrieve resolution
    resolution = extract_resolution(latex_log, dpi)

    # Run the dvi file through dvipng.
    dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" %s "%s"' \
        % (dvipng, resolution, fg_color_dvipng, bg_color_dvipng, pages_parameter, dvi_file)
    dvipng_status, dvipng_stdout = run_command(dvipng_call)

    if dvipng_status:
        warning("%s failed to generate images from %s... fallback to legacy method" \
              % (os.path.basename(dvipng), dvi_file))
        progress("Using the legacy conversion method (dvipng failed)")
        return legacy_conversion_step1(latex_file, dpi, output_format, fg_color,
            bg_color, latex, pdf_output)

    # Extract metrics info from dvipng_stdout.
    metrics_file = latex_file_re.sub(".metrics", latex_file)
    dvipng_metrics = extract_metrics_info(dvipng_stdout)

    # If some pages require PostScript pass them to legacy method
    if len(ps_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, ps_pages)

        # Pass the new LaTeX file to the legacy method
        progress("Pages %s include postscript specials" % ps_pages)
        progress("Using the legacy conversion method (PostScript support)")
        legacy_status, legacy_metrics = legacy_conversion_step1(legacy_latex_file,
            dpi, output_format, fg_color, bg_color, latex, pdf_output, 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, 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:
        error_count = 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))
                error_count += 1
        if error_count:
            warning("Failed to produce %d preview snippet(s)" % error_count)

    # Convert images to ppm format if necessary.
    if output_format == "ppm":
        convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file))

    # Actually create the .metrics file
    write_metrics_info(dvipng_metrics, metrics_file)

    return (0, dvipng_metrics)
Esempio n. 7
0
        elif opt in ("--png", "--ppm"):
            output_format = opt[2:]
        elif opt in ("-v", "--verbose"):
            import lyxpreview_tools
            lyxpreview_tools.verbose = True

    # Determine input file
    if len(args) != 1:
        err = "A single input file is required, %s given" % (len(args) or "none")
        error("%s\n%s" % (err, usage(script_name)))

    input_path = args[0]
    dir, latex_file = os.path.split(input_path)

    # Echo the settings
    progress("Starting %s..." % script_name)
    progress("Output format: %s" % output_format)
    progress("Foreground color: %s" % fg_color)
    progress("Background color: %s" % bg_color)
    progress("Resolution (dpi): %s" % dpi)
    progress("File to process: %s" % input_path)

    # Check for the input file
    if not os.path.exists(input_path):
        error('File "%s" not found.' % input_path)
    if len(dir) != 0:
        os.chdir(dir)

    fg_color_dvipng = make_texcolor(fg_color, False)
    bg_color_dvipng = make_texcolor(bg_color, False)
Esempio n. 8
0
def main(argv):
    # Set defaults.
    dpi = 128
    fg_color = "000000"
    bg_color = "ffffff"
    bibtex = None
    latex = None
    lilypond = False
    lilypond_book = None
    output_format = "png"
    script_name = argv[0]

    # Parse and manipulate the command line arguments.
    try:
        (opts, args) = getopt.gnu_getopt(argv[1:], "dhv", [
            "bibtex=", "bg=", "debug", "dpi=", "fg=", "help", "latex=",
            "lilypond", "lilypond-book=", "png", "ppm", "verbose"
        ])
    except getopt.GetoptError as err:
        error("%s\n%s" % (err, usage(script_name)))

    opts.reverse()
    for opt, val in opts:
        if opt in ("-h", "--help"):
            print(usage(script_name))
            sys.exit(0)
        elif opt == "--bibtex":
            bibtex = [val]
        elif opt == "--bg":
            bg_color = val
        elif opt in ("-d", "--debug"):
            lyxpreview_tools.debug = True
        elif opt == "--dpi":
            try:
                dpi = int(val)
            except:
                error("Cannot convert %s to an integer value" % val)
        elif opt == "--fg":
            fg_color = val
        elif opt == "--latex":
            latex = [val]
        elif opt == "--lilypond":
            lilypond = True
        elif opt == "--lilypond-book":
            lilypond_book = [val]
        elif opt in ("--png", "--ppm"):
            output_format = opt[2:]
        elif opt in ("-v", "--verbose"):
            lyxpreview_tools.verbose = True

    # Determine input file
    if len(args) != 1:
        err = "A single input file is required, %s given" % (len(args)
                                                             or "none")
        error("%s\n%s" % (err, usage(script_name)))

    input_path = args[0]
    dir, latex_file = os.path.split(input_path)

    # Check for the input file
    if not os.path.exists(input_path):
        error('File "%s" not found.' % input_path)
    if len(dir) != 0:
        os.chdir(dir)

    if lyxpreview_tools.verbose:
        f_out = open('verbose.txt', 'a')
        sys.stdout = f_out
        sys.stderr = f_out

    # Echo the settings
    progress("Running Python %s" % str(sys.version_info[:3]))
    progress("Starting %s..." % script_name)
    if os.name == "nt":
        progress("Use win32_modules: %d" % lyxpreview_tools.use_win32_modules)
    progress("Output format: %s" % output_format)
    progress("Foreground color: %s" % fg_color)
    progress("Background color: %s" % bg_color)
    progress("Resolution (dpi): %s" % dpi)
    progress("File to process: %s" % input_path)

    # For python > 2 convert strings to bytes
    if not PY2:
        fg_color = bytes(fg_color, 'ascii')
        bg_color = bytes(bg_color, 'ascii')

    fg_color_dvipng = make_texcolor(fg_color, False)
    bg_color_dvipng = make_texcolor(bg_color, False)

    # For python > 2 convert bytes to string
    if not PY2:
        fg_color_dvipng = fg_color_dvipng.decode('ascii')
        bg_color_dvipng = bg_color_dvipng.decode('ascii')

    # External programs used by the script.
    latex = find_exe_or_terminate(latex or latex_commands)
    bibtex = find_exe(bibtex or bibtex_commands)
    if lilypond:
        lilypond_book = find_exe_or_terminate(lilypond_book
                                              or ["lilypond-book --safe"])

    # These flavors of latex are known to produce pdf output
    pdf_output = latex in pdflatex_commands

    progress("Latex command: %s" % latex)
    progress("Latex produces pdf output: %s" % pdf_output)
    progress("Bibtex command: %s" % bibtex)
    progress("Lilypond-book command: %s" % lilypond_book)
    progress("Preprocess through lilypond-book: %s" % lilypond)
    progress("Altering the latex file for font size and colors")

    # Make sure that multiple defined macros and the microtype package
    # don't cause issues in the latex file.
    fix_latex_file(latex_file, pdf_output)

    if lilypond:
        progress("Preprocess the latex file through %s" % lilypond_book)
        if pdf_output:
            lilypond_book += " --pdf"
        lilypond_book += " --latex-program=%s" % latex.split()[0]

        # Make a copy of the latex file
        lytex_file = latex_file_re.sub(".lytex", latex_file)
        shutil.copyfile(latex_file, lytex_file)

        # Preprocess the latex file through lilypond-book.
        lytex_status, lytex_stdout = run_tex(lilypond_book, lytex_file)

    if pdf_output:
        progress("Using the legacy conversion method (PDF support)")
        return legacy_conversion_step1(latex_file, dpi, output_format,
                                       fg_color, bg_color, latex, pdf_output)

    # This can go once dvipng becomes widespread.
    dvipng = find_exe(["dvipng"])
    if dvipng == None:
        progress("Using the legacy conversion method (dvipng not found)")
        return legacy_conversion_step1(latex_file, dpi, output_format,
                                       fg_color, bg_color, latex, pdf_output)

    dv2dt = find_exe(["dv2dt"])
    if dv2dt == None:
        progress("Using the legacy conversion method (dv2dt not found)")
        return legacy_conversion_step1(latex_file, dpi, output_format,
                                       fg_color, bg_color, latex, pdf_output)

    pngtopnm = ""
    if output_format == "ppm":
        pngtopnm = find_exe(["pngtopnm"])
        if pngtopnm == None:
            progress("Using the legacy conversion method (pngtopnm not found)")
            return legacy_conversion_step1(latex_file, dpi, output_format,
                                           fg_color, bg_color, latex,
                                           pdf_output)

    # Compile the latex file.
    error_pages = []
    latex_status, latex_stdout = run_latex(latex, latex_file, bibtex)
    latex_log = latex_file_re.sub(".log", latex_file)
    if latex_status:
        progress("Will try to recover from %s failure" % latex)
        error_pages = check_latex_log(latex_log)

    # The dvi output file name
    dvi_file = latex_file_re.sub(".dvi", latex_file)

    # If there's no DVI output, look for PDF and go to legacy or fail
    if not os.path.isfile(dvi_file):
        # No DVI, is there a PDF?
        pdf_file = latex_file_re.sub(".pdf", latex_file)
        if os.path.isfile(pdf_file):
            progress("%s produced a PDF output, fallback to legacy." \
                % (os.path.basename(latex)))
            progress("Using the legacy conversion method (PDF support)")
            return legacy_conversion_step1(latex_file, dpi, output_format,
                                           fg_color, bg_color, latex, True)
        else:
            error("No DVI or PDF output. %s failed." \
                % (os.path.basename(latex)))

    # 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, pdf_pages, page_count,
     pages_parameter) = find_ps_pages(dvi_file)

    # 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)

    # Retrieve resolution
    resolution = extract_resolution(latex_log, dpi)

    # Run the dvi file through dvipng.
    dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" %s "%s"' \
        % (dvipng, resolution, fg_color_dvipng, bg_color_dvipng, pages_parameter, dvi_file)
    dvipng_status, dvipng_stdout = run_command(dvipng_call)

    if dvipng_status:
        warning("%s failed to generate images from %s... fallback to legacy method" \
              % (os.path.basename(dvipng), dvi_file))
        progress("Using the legacy conversion method (dvipng failed)")
        return legacy_conversion_step1(latex_file, dpi, output_format,
                                       fg_color, bg_color, latex, pdf_output)

    # Extract metrics info from dvipng_stdout.
    metrics_file = latex_file_re.sub(".metrics", latex_file)
    dvipng_metrics = extract_metrics_info(dvipng_stdout)

    # If some pages require PostScript pass them to legacy method
    if len(ps_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, ps_pages)

        # Pass the new LaTeX file to the legacy method
        progress("Pages %s include postscript specials" % ps_pages)
        progress("Using the legacy conversion method (PostScript support)")
        legacy_status, legacy_metrics = legacy_conversion_step1(
            legacy_latex_file, dpi, output_format, fg_color, bg_color, latex,
            pdf_output, 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, 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:
        error_count = 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))
                error_count += 1
        if error_count:
            warning("Failed to produce %d preview snippet(s)" % error_count)

    # Convert images to ppm format if necessary.
    if output_format == "ppm":
        convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file))

    # Actually create the .metrics file
    write_metrics_info(dvipng_metrics, metrics_file)

    return (0, dvipng_metrics)
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 and os.name == 'nt':
        # On Windows, check for png support (see #10718)
        conv_status, conv_stdout = run_command("%s --help" % pdftocairo)
        use_pdftocairo = '-png' in conv_stdout
    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)

    # 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
    if resolution > 150:
        alpha = 2

    gs_device = "png16m"
    gs_ext = "png"
    if output_format == "ppm":
        gs_device = "pnmraw"
        gs_ext = "ppm"

    # Extract the metrics from the log file
    legacy_metrics = legacy_extract_metrics_info(log_file)

    # List of pages which failed to produce a correct output
    failed_pages = []

    # Generate the bitmap images
    if dvips_failed:
        # dvips failed, maybe there's a PDF, try to produce bitmaps
        if use_pdftocairo:
            conv_call = '%s -png -transp -r %d "%s" "%s"' \
                        % (pdftocairo, 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"' \
                      % (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 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_root)
        ps_files.sort()

        # Call the converter for each file
        for file in ps_files:
            i = i + 1
            progress("Processing 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:
        warning("Now trying to obtain failed previews through pdflatex")
        error_count = legacy_conversion_pdflatex(latex_file, failed_pages,
                                                 legacy_metrics,
                                                 use_pdftocairo, conv,
                                                 gs_device, gs_ext, alpha,
                                                 resolution, output_format)
    else:
        error_count = 0

    # 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))
                error_count += 1

    # 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)
    if not skipMetrics:
        # Extract metrics info from the log file.
        metrics_file = latex_file_re.sub(".metrics", latex_file)
        write_metrics_info(legacy_metrics, metrics_file)
        if error_count:
            warning("Failed to produce %d preview snippet(s)" % error_count)

    return (0, legacy_metrics)
Esempio n. 10
0
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"])

    # 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.
    log_file = latex_file_re.sub(".log", latex_file)
    resolution = extract_resolution(log_file, dpi)

    # Older versions of gs have problems with a large degree of
    # anti-aliasing at high resolutions
    alpha = 4
    if resolution > 150:
        alpha = 2

    gs_device = "png16m"
    gs_ext = "png"
    if output_format == "ppm":
        gs_device = "pnmraw"
        gs_ext = "ppm"

    # Extract the metrics from the log file
    legacy_metrics = legacy_extract_metrics_info(log_file)

    # List of pages which failed to produce a correct output
    failed_pages = []

    # 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)

        gs_status, gs_stdout = run_command(gs_call)
        if gs_status:
            error("Failed: %s %s" % (os.path.basename(gs), ps_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)

        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.sort()

        # Call GhostScript 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))
                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)

    # Crop the images
    if pnmcrop != None:
        crop_files(pnmcrop, latex_file_re.sub("", latex_file))

    # Allow to skip .metrics creation for custom management
    # (see the dvipng method)
    if not skipMetrics:
        # Extract metrics info from the log file.
        metrics_file = latex_file_re.sub(".metrics", latex_file)
        write_metrics_info(legacy_metrics, metrics_file)

    return (0, legacy_metrics)