+# Returns a tuple of:
+# ps_pages: list of page indexes of pages containing PS literals
+# page_count: total number of pages
+# pages_parameter: parameter for dvipng to exclude pages with PostScript
+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
+ # This is required for correct rendering of PSTricks and TikZ
+ dv2dt = find_exe_or_terminate(["dv2dt"])
+ dv2dt_call = '%s "%s"' % (dv2dt, 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:)")
+
+ # 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.
+ page_has_ps = False
+ page_index = 0
+ ps_pages = []
+
+ for line in dv2dt_output.split("\n"):
+ # New page
+ if line.startswith("bop"):
+ page_has_ps = 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 psliteral_re.match(line) != None:
+ # Literal PostScript special detected!
+ page_has_ps = 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
+ # wanted pages through the -pp parameter. E.g., dvipng -pp 4-12,14,64
+ pages_parameter = " -pp "
+ skip = True
+ last = -1
+
+ # 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:
+ # 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.
+ pages_parameter += str(index)
+ # Save the starting index to avoid things such as "11-11"
+ last = index
+ # We're not skipping anymore
+ skip = False
+ elif (index in ps_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
+ # then it's not a range
+ pages_parameter += "-" + str(index - 1)
+
+ # Add a separator
+ pages_parameter += ","
+ # Now we're skipping
+ skip = True
+
+ # 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):
+ pages_parameter += "-" + str(index)
+
+ return (ps_pages, page_index, pages_parameter)