예제 #1
0
파일: latex.py 프로젝트: ikicic/skoljka
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
예제 #2
0
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
예제 #3
0
파일: views.py 프로젝트: ikicic/skoljka
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))
예제 #4
0
파일: latex.py 프로젝트: ikicic/skoljka
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
예제 #5
0
파일: latex.py 프로젝트: ikicic/skoljka
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