def generate_png(hash, format, latex): latex = latex.strip() path = os.path.normpath(os.path.join( settings.MEDIA_ROOT, 'm', hash[0], hash[1], hash[2])) if not os.path.exists(path): os.makedirs(path) filename = os.path.normpath(os.path.join(path, hash)) f = codecs.open(filename + '.tex', 'w', encoding='utf-8') data = {'equation': unicode(format) % latex} f.write(render_to_string('latex_inline.tex', data)) f.close() # TODO: handle errors # TODO: disable logs cmd = '%s -output-directory=%s -interaction=batchmode %s.tex' % \ (latex_full_filename('latex'), os.path.dirname(filename), filename) error = run_command(cmd, timeout=5) if not error: # TODO: handle errors and test quality cmd = "%s -bg Transparent --gamma 1.5 -D 120 --depth* -T tight --strict -o %s.png %s" % (latex_full_filename('dvipng'), filename, filename) status, stdout = getstatusoutput(cmd) # Fixing $\newline$ bug. dvipng would return depth=2^31-1. # In case we get something like this, do not output weird html, rather mark # the latex as invalid. MAX_DEPTH = 10000 depth = ERROR_DEPTH_VALUE if not error and status == 0: depth_re = re.compile(r'.*\[\d+ depth=(-?\d+)\]') for line in stdout.splitlines(): m = depth_re.match(line.strip()) if m: depth = int(m.group(1)) break if depth > MAX_DEPTH: depth = ERROR_DEPTH_VALUE if depth == ERROR_DEPTH_VALUE: print 'ERROR stdout:', stdout if not error and status == 0: os.remove(filename + '.tex') os.remove(filename + '.log') os.remove(filename + '.aux') os.remove(filename + '.dvi') latex_element = LatexElement( hash=hash, text=latex, format=format, depth=depth) latex_element.save(force_insert=True) return latex_element
def create_file_thumbnail(filename): filename_no_ext, ext = os.path.splitext(filename) if not ext or ext[0] != '.': return ext = ext[1:] if ext not in ['pdf', 'ps', 'jpg', 'jpeg', 'bmp', 'png', 'svg']: return thumbnail_name = filename_no_ext + '-thumb200x150.png' cmd = "convert -thumbnail '200x150^' -crop 200x150+0+0 +repage {}[0] {}" cmd = cmd.format(filename, thumbnail_name) error = run_command(cmd, timeout=5) if error: raise ThumbnailRenderingException(error) return thumbnail_name
def _export(ids, sorted_tasks, tasks, form, ignore_exceptions): """ Output LaTeX or PDF, permission already checked. It is assumed that Attachments are already saved in tasks[...] as .cache_file_list """ format = form.cleaned_data['format'] if format not in ['latex', 'pdf']: return (400, 'Export format not valid') # Please note that .tex created for .pdf is not the same as .tex for # exporting (e.g. there are differences in the attachment path). # Those two cases will be distinguished by different hashes. hash = hashlib.md5(repr((ids, form.cleaned_data))).hexdigest() create_archive = form.cleaned_data['create_archive'] filename = os.path.normpath(os.path.join(settings.LOCAL_DIR, 'media/export/task' + hash)) # no extension # check if output already exists ext = '.pdf' if format == 'pdf' else '.tex' fext = '.zip' if create_archive else ext # final ext # TODO: check if archive exists (currently, it is not trivially possible # to check if there were some changes to attachments) if not settings.DEBUG \ and not create_archive \ and os.path.exists(filename + fext): oldest_file_mtime = \ tasks.aggregate(Min('last_edit_date'))['last_edit_date__min'] full_path = os.path.getmtime(filename + fext) if datetime.datetime.fromtimestamp(full_path) > oldest_file_mtime: # already up-to-date return HttpResponseRedirect( '/media/export/task{}{}'.format(hash, fext)) latex = _convert_to_latex(sorted_tasks, ignore_exceptions, **form.cleaned_data) # if latex without archive, do not create file, but directly output it if format == 'latex' and not create_archive: response = HttpResponse(content=latex, content_type='application/x-latex') response['Content-Disposition'] = 'filename=taskexport.tex' return response # otherwise, save generated latex into a file f = codecs.open(filename + '.tex', 'w', encoding='utf-8') f.write(latex) f.close() if format == 'pdf': error = run_command('pdflatex -output-directory=%s -interaction=batchmode %s.tex' \ % (os.path.dirname(filename), filename), timeout=10) if error: return HttpResponseServerError('LaTeX generation error! Error code: %d' % error) # error = run_command('dvipdfm -o %s %s' % (filename + '.pdf', filename), timeout=10) # if error: # return HttpResponseServerError('dvipdfm Error %d!' % error) # os.remove(filename + '.tex') # os.remove(filename + '.log') # os.remove(filename + '.aux') # os.remove(filename + '.dvi') if create_archive: f = zipfile.ZipFile(filename + '.zip', mode='w', compression=zipfile.ZIP_DEFLATED) f.write(filename + ext, 'task{}{}'.format(hash, ext)) for task in tasks: for k in range(len(task.cache_file_list)): attachment = task.cache_file_list[k] f.write(attachment.file.name, '{}/{}/{}/{}'.format( ZIP_ATTACHMENT_DIR, task.id, k, attachment.get_filename())) f.close() return HttpResponseRedirect('/media/export/task{}{}'.format(hash, fext))
def generate_png(eq, format): eq = eq.strip() eq_hash = hashlib.md5((eq + format).encode("utf-8")).hexdigest() try: latex_element = LatexElement.objects.only("depth").get(hash=eq_hash) return eq_hash, latex_element.depth except: pass path = os.path.normpath(os.path.join(settings.MEDIA_ROOT, "m", eq_hash[0], eq_hash[1], eq_hash[2])) if not os.path.exists(path): os.makedirs(path) filename = os.path.normpath(os.path.join(path, eq_hash)) f = codecs.open(filename + ".tex", "w", encoding="utf-8") data = {"equation": unicode(format) % eq} f.write(render_to_string("latex_inline.tex", data)) f.close() # TODO: handle errors # TODO: disable logs cmd = "%s -output-directory=%s -interaction=batchmode %s.tex" % ( latex_full_filename("latex"), os.path.dirname(filename), filename, ) error = run_command(cmd, timeout=5) if not error: # TODO: handle errors and test quality cmd = "%s -bg Transparent --gamma 1.5 -D 120 --depth* -T tight --strict -o %s.png %s" % ( latex_full_filename("dvipng"), filename, filename, ) svgcmd = "%s -p 1 -n -o %s.svg %s" % (latex_full_filename("dvisvgm"), filename, filename) status, stdout = getstatusoutput(cmd) # Fixing $\newline$ bug. dvipng would return depth=2^31-1. # In case we get something like this, do not output weird html, rather mark # the latex as invalid. MAX_DEPTH = 10000 depth = ERROR_DEPTH_VALUE if not error and status == 0: depth_re = re.compile(r".*\[\d+ depth=(-?\d+)\]") for line in stdout.splitlines(): m = depth_re.match(line.strip()) if m: depth = int(m.group(1)) break if depth > MAX_DEPTH: depth = ERROR_DEPTH_VALUE if depth == ERROR_DEPTH_VALUE: print "ERROR stdout:", stdout if not error and status == 0: os.remove(filename + ".tex") os.remove(filename + ".log") os.remove(filename + ".aux") os.remove(filename + ".dvi") latex_element = LatexElement(hash=eq_hash, text=eq, format=format, depth=depth) latex_element.save(force_insert=True) return eq_hash, depth
def generate_svg(eq, format, inline): eq_hash = hashlib.md5((eq + format).encode("utf-8")).hexdigest() # try: # latex_element = LatexElement.objects.only("depth").get(hash=eq_hash) # return eq_hash, latex_element.depth # except: # pass path = os.path.normpath(os.path.join(settings.MEDIA_ROOT, "m", eq_hash[0], eq_hash[1], eq_hash[2])) if not os.path.exists(path): os.makedirs(path) filename = os.path.normpath(os.path.join(path, eq_hash)) f = codecs.open(filename + ".tex", "w", encoding="utf-8") f.write(tex_preamble_svg) f.write(r"""\newcommand{\MYFORMULA}{""" + (unicode(format) % eq) + "}") if inline: f.write("\setbox0\hbox{\MYFORMULA}") f.write(r"""\begin{preview}\MYFORMULA\end{preview}""") if inline: f.write(depth_out_1 + unicode(eq_hash + ".dat") + depth_out_2) f.write("\end{document}") f.close() # TODO: handle errors # TODO: disable logs cmd = "%s -output-directory=%s -interaction=batchmode %s.tex" % ( latex_full_filename("latex"), os.path.dirname(filename), filename, ) error = run_command(cmd, timeout=5) if not error: cmd = "%s -p 1 -n -o %s.svg %s.dvi" % (latex_full_filename("dvisvgm"), filename, filename) status, stdout = getstatusoutput( cmd ) # there is a bug in the latest dvisvgm version - there are TeX pt's in SVG file instead of CSS pt's print stdout if not error and status == 0 and not inline: depth = 0 elif not error and status == 0 and inline: page_size_re = re.compile("\s*page size: (\d+\.\d+)pt x (\d+\.\d+)pt \((\d+\.\d+)mm x (\d+\.\d+)mm\)") for line in stdout.splitlines(): print line m = page_size_re.match(line) if m: height = float(m.group(2)) # these are TeX pt's (1in = 72.27pt) height = height * 72 / 72.27 # these are CSS pt's (1in = 72pt) break # open .dat file, parse and set depth with following formula f = open(filename + ".dat", "r") line = f.readline() f.close() dat_file_re = re.compile("box_height=(\d+\.\d+)pt,box_depth=(\d+\.\d+)pt,box_width=(\d+\.\d+)pt") m = dat_file_re.match(line) if m: box_height = float(m.group(1)) box_depth = float(m.group(2)) box_width = float(m.group(3)) depth = height * box_depth / (box_depth + box_height) print depth else: depth = ERROR_DEPTH_VALUE else: # error depth = ERROR_DEPTH_VALUE # if not error and status == 0: # os.remove(filename + '.tex') # os.remove(filename + '.log') # os.remove(filename + '.aux') # os.remove(filename + '.dvi') # os.remove(filename + '.dat') latex_element = LatexElement(hash=eq_hash, text=eq, format=format, depth=depth) # latex_element.save(force_insert=True) return eq_hash, depth