import json import math import os import subprocess import time import cairocffi as cairo import flask import img2pdf import pangocffi as pango import pangocairocffi as pangocairo import requests app = flask.Flask(__name__) class Renderer(object): INCH_PER_MM = 0.039 DPI = 300 def __init__(self, size=(36, 89)): width, height = [int(s * self.INCH_PER_MM * self.DPI) for s in size] surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) context = cairo.Context(surface) context.rectangle(0, 0, width, height) context.set_source_rgb(1, 1, 1) context.fill() context.translate(width, 0) context.rotate(math.pi/2) self.width, self.height = height, width self.font = pango.FontDescription() self.context = context self.surface = surface def export_png(self, name): with open(name, 'wb') as f: self.surface.write_to_png(f) def render_text(self, text, fontname, x, y, html=False): print("Fontname:", fontname) self.context.save() if y != -1: self.context.translate(x, y) self.context.set_antialias(cairo.ANTIALIAS_SUBPIXEL) layout = pangocairo.create_layout(self.context) layout._set_width(pango.units_from_double(self.width)) layout._set_alignment(pango.Alignment.CENTER) if html: # Absolutely horrifying hack to fix broken text wrapping layout.apply_markup('%s' % (fontname, text)) else: self.font.family = fontname.split()[0] self.font.size = pango.units_from_double(int(fontname.split()[1])) layout.font_description = self.font layout.text = text if y == -1: self.context.translate(0, (self.height - pango.units_to_double(layout.get_size()[1]))/2) self.context.set_source_rgb(0, 0, 0) pangocairo.update_layout(self.context, layout) pangocairo.show_layout(self.context, layout) self.context.restore() @app.route('/') def index(): return flask.render_template('index.html') @app.route('/api/preview//') def stuff_preview(size): text = flask.request.args.get('text') html = flask.request.args.get('html') == '1' renderer = Renderer() renderer.render_text(text, 'Sans {}'.format(size), 0, -1, html) preview = renderer.surface.write_to_png() return flask.Response(preview, mimetype='image/png') DELAY = 5 @app.route('/api/print//', methods=['POST']) def stuff_print(size): text = flask.request.args.get('text') html = flask.request.args.get('html') == '1' renderer = Renderer() renderer.render_text(text, 'Sans {}'.format(size), 0, -1, html) data = renderer.surface.write_to_png() response = requests.post( os.environ.get('PRINTSERVANT_HOST') + '/print', params={'printer': 'dymo', 'copies': 1}, data=data, headers={'Content-Type': 'image/png'}, ) print('Printing job response', response) if response.status_code != 200: return flask.Response(f"{response.text} ({response.status_code})", status=response.status_code) return 'ok' def main(): app.run(host="0.0.0.0", port=5000, debug=True) if __name__ == '__main__': main()