labelmaker/labelmaker/main.py

118 lines
3.6 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
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 get_preview(self):
new_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
context = cairo.Context(new_surface)
context.translate(0, self.height)
# 360 no scope
context.rotate(-90.0*math.pi/180.0)
context.set_source_surface(self.surface, 0, 0)
context.paint()
return new_surface.write_to_png()
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.get_preview()
return flask.Response(preview, mimetype='image/png')
DELAY = 5
@app.route('/api/print/<int:size>/', 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()