예제 #1
0
    def render(self, source):
        proc = Subprocess(['docker', 'run', '-i', 'dmoj/texbox:latest'],
                          stdin=Subprocess.STREAM,
                          stdout=Subprocess.STREAM,
                          stderr=Subprocess.STREAM)
        input_task = self._write_and_close(proc.stdin, utf8bytes(source))
        _, output, log = yield [
            input_task,
            proc.stdout.read_until_close(),
            proc.stderr.read_until_close()
        ]

        try:
            yield proc.wait_for_exit()
        except subprocess.CalledProcessError:
            raise RuntimeError('Failed to run docker, full log:\n' +
                               utf8text(log, errors='backslashreplace'))

        try:
            width, height, svg_len = header.unpack(output[:header.size])
            svg = output[header.size:header.size + svg_len]
            rest = output[header.size + svg_len:]
            png_len, = size_struct.unpack(rest[:size_struct.size])
            png = rest[size_struct.size:size_struct.size + png_len]
        except struct.error:
            raise RuntimeError('corrupted output from texbox')

        if len(svg) != svg_len or b'<svg' not in svg:
            raise RuntimeError('corrupted SVG file from texbox')

        if len(png) != png_len or b'\x89PNG' not in png:
            raise RuntimeError('corrupted PNG file from texbox')

        return {
            'svg': utf8text(svg),
            'png': png,
            'meta': {
                'width': width,
                'height': height
            }
        }
예제 #2
0
    def dvi_to_svg(self):
        dvisvgm = Subprocess([
            self.backend.dvisvgm_path, '--verbosity=1', '--no-fonts',
            'render.dvi'
        ],
                             stdout=Subprocess.STREAM,
                             stderr=subprocess.STDOUT,
                             cwd=self.dir)

        log = yield dvisvgm.stdout.read_until_close()
        try:
            yield dvisvgm.wait_for_exit()
        except subprocess.CalledProcessError:
            raise RuntimeError('Failed to run dvisvgm, full log:\n' +
                               utf8text(log, errors='backslashreplace'))
예제 #3
0
    def latex_to_dvi(self):
        latex = Subprocess([
            self.backend.latex_path, '-halt-on-error',
            '-interaction=nonstopmode', 'render.tex'
        ],
                           stdout=Subprocess.STREAM,
                           stderr=subprocess.STDOUT,
                           cwd=self.dir)

        log = yield latex.stdout.read_until_close()
        try:
            yield latex.wait_for_exit()
        except subprocess.CalledProcessError:
            raise RuntimeError('Failed to run latex, full log:\n' +
                               utf8text(log, errors='backslashreplace'))
예제 #4
0
    def render(self, source):
        with open(os.path.join(self.dir, 'render.tex'), 'wb') as f:
            f.write(utf8bytes(source))

        yield self.latex_to_dvi()
        yield self.dvi_to_svg()
        png, width, height = yield self.svg_to_png()
        with open(os.path.join(self.dir, 'render.svg'), 'rb') as f:
            svg = utf8text(f.read())
        return {
            'png': png,
            'svg': svg,
            'meta': {
                'width': width,
                'height': height
            }
        }
예제 #5
0
    def svg_to_png(self):
        convert = Subprocess(
            [self.backend.convert_path, '-identify', 'render.svg', 'png:-'],
            cwd=self.dir,
            stderr=Subprocess.STREAM,
            stdin=self.devnull,
            stdout=Subprocess.STREAM)
        out, err = yield [
            convert.stdout.read_until_close(),
            convert.stderr.read_until_close()
        ]
        try:
            yield convert.wait_for_exit()
        except subprocess.CalledProcessError:
            raise RuntimeError('Failed to run convert, full log:\n' +
                               utf8text(log, errors='backslashreplace'))

        ident, _, out = out.partition(b'\n')
        width, height = redimensions.match(ident).groups()
        return out, int(width), int(height)