labelmaker/labelmaker/main.py

112 lines
3.4 KiB
Python

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
class App(flask.Flask):
def __init__(self, *args, **kwargs):
super(App, self).__init__(*args, **kwargs)
self.last = 0
app = App(__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('<span font_desc="%s">%s</span>' % (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/<int:size>/')
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/<int:size>/', methods=['POST'])
def stuff_print(size):
last = app.last
print(last, time.time() - last)
if time.time() - last < DELAY:
return 'Please wait {} more seconds before next print.'.format(int(DELAY - (time.time() - last)))
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()
payload = {'printer': 'dymo_labelwriter450', 'copies': 1, 'body': data}
r = requests.post(os.environ.get('PRINTSERVANT_HOST') + '/print', params=payload)
print('Printing job response', r.text)
app.last = time.time()
return 'ok'
def main():
app.run(host="0.0.0.0", port=5000, debug=True)
if __name__ == '__main__':
main()