diff --git a/src/pretix/base/invoice.py b/src/pretix/base/invoice.py index 113294bb8c..8ba7c096b1 100644 --- a/src/pretix/base/invoice.py +++ b/src/pretix/base/invoice.py @@ -184,10 +184,15 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer): class ThumbnailingImageReader(ImageReader): def resize(self, width, height, dpi): + if width is None: + width = height * self._image.size[0] / self._image.size[1] + if height is None: + height = width * self._image.size[1] / self._image.size[0] self._image.thumbnail( size=(int(width * dpi / 72), int(height * dpi / 72)), resample=BICUBIC ) + return width, height class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer): diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 26364d3708..2347583fe8 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -24,6 +24,7 @@ from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfgen.canvas import Canvas from reportlab.platypus import Paragraph +from pretix.base.invoice import ThumbnailingImageReader from pretix.base.models import Order, OrderPosition from pretix.base.signals import layout_text_variables from pretix.base.templatetags.money import money_filter @@ -210,6 +211,22 @@ class Renderer: if 'bolditalic' in styles: pdfmetrics.registerFont(TTFont(family + ' B I', finders.find(styles['bolditalic']['truetype']))) + def _draw_poweredby(self, canvas: Canvas, op: OrderPosition, o: dict): + content = o.get('content', 'dark') + img = finders.find('pretixpresale/pdf/powered_by_pretix_{}.png'.format(content)) + + ir = ThumbnailingImageReader(img) + try: + width, height = ir.resize(None, float(o['size']) * mm, 300) + except: + logger.exception("Can not resize image") + pass + canvas.drawImage(ir, + float(o['left']) * mm, float(o['bottom']) * mm, + width=width, height=height, + preserveAspectRatio=True, anchor='n', + mask='auto') + def _draw_barcodearea(self, canvas: Canvas, op: OrderPosition, o: dict): content = o.get('content', 'secret') if content == 'secret': @@ -284,6 +301,8 @@ class Renderer: self._draw_barcodearea(canvas, op, o) elif o['type'] == "textarea": self._draw_textarea(canvas, op, order, o) + elif o['type'] == "poweredby": + self._draw_poweredby(canvas, op, o) canvas.showPage() def render_background(self, buffer, title=_('Ticket')): diff --git a/src/pretix/control/templates/pretixcontrol/pdf/index.html b/src/pretix/control/templates/pretixcontrol/pdf/index.html index 17d7eec75d..893b0d2273 100644 --- a/src/pretix/control/templates/pretixcontrol/pdf/index.html +++ b/src/pretix/control/templates/pretixcontrol/pdf/index.html @@ -2,7 +2,7 @@ {% load i18n %} {% load staticfiles %} {% load compress %} -{% block title %}{% trans "PDF Ticket Editor" %}{% endblock %} +{% block title %}{% trans "PDF Editor" %}{% endblock %} {% block custom_header %} {{ block.super }} {% compress css %} @@ -204,7 +204,7 @@ id="toolbox-position-y"> -
+
{% for family, styles in fonts.items %}
{% for style, formats in styles.items %}
diff --git a/src/pretix/plugins/ticketoutputpdf/migrations/0003_auto_20180710_1321.py b/src/pretix/plugins/ticketoutputpdf/migrations/0003_auto_20180710_1321.py
new file mode 100644
index 0000000000..8580f8dedf
--- /dev/null
+++ b/src/pretix/plugins/ticketoutputpdf/migrations/0003_auto_20180710_1321.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import json
+
+from django.db import migrations
+from django.db.models import Q
+
+
+def add_pretix_logo(app, schema_editor):
+ TicketLayout = app.get_model('ticketoutputpdf', 'TicketLayout')
+ for tl in TicketLayout.objects.filter(Q(background__isnull=True) | Q(background="")):
+ l = json.loads(tl.layout)
+ l.append({"type": "poweredby", "left": "88.72", "bottom": "10.00", "size": "20.00", "content": "dark"})
+ tl.layout = json.dumps(l)
+ tl.save(update_fields=['layout'])
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('ticketoutputpdf', '0002_auto_20180605_2022'),
+ ]
+
+ operations = [
+ migrations.RunPython(add_pretix_logo, migrations.RunPython.noop)
+ ]
diff --git a/src/pretix/plugins/ticketoutputpdf/models.py b/src/pretix/plugins/ticketoutputpdf/models.py
index bbb191aa17..4310d699e2 100644
--- a/src/pretix/plugins/ticketoutputpdf/models.py
+++ b/src/pretix/plugins/ticketoutputpdf/models.py
@@ -53,7 +53,8 @@ class TicketLayout(LoggedModel):
'"type": "textarea"}, {"italic": false, "bottom": "194.50", "align": "left", "fontfamily": "Open '
'Sans", "width": "90.00", "left": "102.50", "text": "tdmruoekvkpbv1o2mv8xccvqcikvr58u", "content": '
'"secret", "fontsize": "13.0", "bold": false, "color": [0, 0, 0, 1], "type": "textarea"}, '
- '{"left": "130.40", "bottom": "204.50", "type": "barcodearea", "size": "64.00"}]'
+ '{"left": "130.40", "bottom": "204.50", "type": "barcodearea", "size": "64.00"},{"type":"poweredby",'
+ '"left":"88.72","bottom":"10.00","size":"20.00","content":"dark"}]'
)
background = models.FileField(null=True, blank=True, upload_to=bg_name, max_length=255)
diff --git a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py
index e9d0f951ca..86e427a159 100644
--- a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py
+++ b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py
@@ -157,7 +157,8 @@ class PdfTicketOutput(BaseTicketOutput):
{"type": "textarea", "left": "102.50", "bottom": "194.50", "fontsize": "13.0", "color": [0, 0, 0, 1],
"fontfamily": "Open Sans", "bold": False, "italic": False, "width": "90.00", "content": "secret",
"text": "tdmruoekvkpbv1o2mv8xccvqcikvr58u", "align": "left"},
- {"type": "barcodearea", "left": "130.40", "bottom": "204.50", "size": "64.00"}
+ {"type": "barcodearea", "left": "130.40", "bottom": "204.50", "size": "64.00"},
+ {"type": "poweredby", "left": "88.72", "bottom": "10.00", "size": "20.00"},
]
def _migrate_from_old_settings(self):
diff --git a/src/pretix/static/pretixcontrol/js/ui/editor.js b/src/pretix/static/pretixcontrol/js/ui/editor.js
index 17ba02bf0d..2511ed1317 100644
--- a/src/pretix/static/pretixcontrol/js/ui/editor.js
+++ b/src/pretix/static/pretixcontrol/js/ui/editor.js
@@ -1,4 +1,25 @@
/*globals $, gettext, fabric, PDFJS*/
+fabric.Poweredby = fabric.util.createClass(fabric.Image, {
+ type: 'poweredby',
+
+ initialize: function (options) {
+ options || (options = {});
+
+ this.callSuper('initialize', $("#poweredby-" + options.content).get(0), options);
+ this.set('label', options.label || '');
+ },
+
+ toObject: function () {
+ return fabric.util.object.extend(this.callSuper('toObject'), {});
+ },
+
+ _render: function (ctx) {
+ this.callSuper('_render', ctx);
+ },
+});
+fabric.Poweredby.fromObject = function (object, callback, forceAsync) {
+ return fabric.Object._fromObject('Poweredby', object, callback, forceAsync);
+};
fabric.Barcodearea = fabric.util.createClass(fabric.Rect, {
type: 'barcodearea',
@@ -119,6 +140,14 @@ var editor = {
size: editor._px2mm(o.height * o.scaleY).toFixed(2),
content: o.content,
});
+ } else if (o.type === "poweredby") {
+ d.push({
+ type: "poweredby",
+ left: editor._px2mm(left).toFixed(2),
+ bottom: editor._px2mm(editor.pdf_viewport.height - o.height * o.scaleY - top).toFixed(2),
+ size: editor._px2mm(o.height * o.scaleY).toFixed(2),
+ content: o.content,
+ });
}
}
return d;
@@ -129,6 +158,10 @@ var editor = {
o = editor._add_qrcode();
o.content = d.content;
o.scaleToHeight(editor._mm2px(d.size));
+ } else if (d.type === "poweredby") {
+ o = editor._add_poweredby(d.content);
+ o.content = d.content;
+ o.scaleToHeight(editor._mm2px(d.size));
} else if (d.type === "textarea" || o.type === "text") {
o = editor._add_text();
o.setColor('rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')');
@@ -289,6 +322,9 @@ var editor = {
if (o.type === "barcodearea") {
$("#toolbox-squaresize").val(editor._px2mm(o.height * o.scaleY).toFixed(2));
+ } else if (o.type === "poweredby") {
+ $("#toolbox-squaresize").val(editor._px2mm(o.height * o.scaleY).toFixed(2));
+ $("#toolbox-poweredby-style").val(o.content);
} else if (o.type === "text" || o.type === "textarea") {
var col = (new fabric.Color(o.getFill()))._source;
$("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1));
@@ -334,6 +370,23 @@ var editor = {
o.setScaleX(1);
o.setScaleY(1);
o.set('top', new_top)
+ } else if (o.type === "poweredby") {
+ var new_h = Math.max(1, editor._mm2px($("#toolbox-squaresize").val()));
+ new_top += o.height * o.scaleY - new_h;
+ o.setWidth(new_h / o.height * o.width);
+ o.setHeight(new_h);
+ o.setScaleX(1);
+ o.setScaleY(1);
+ o.set('top', new_top)
+ if ($("#toolbox-poweredby-style").val() !== o.content) {
+ var data = editor.dump([o]);
+ data[0].content = $("#toolbox-poweredby-style").val();
+ var newo = editor._add_from_data(data[0]);
+ o.remove();
+ editor.fabric.discardActiveGroup();
+ editor.fabric.discardActiveObject();
+ editor.fabric.setActiveObject(newo);
+ }
} else if (o.type === "textarea" || o.type === "text") {
o.setColor($("#toolbox-col").val());
o.setFontSize(editor._pt2px($("#toolbox-fontsize").val()));
@@ -371,6 +424,8 @@ var editor = {
$("#toolbox-heading").text(gettext("Text object"));
} else if (o.type === "barcodearea") {
$("#toolbox-heading").text(gettext("Barcode area"));
+ } else if (o.type === "poweredby") {
+ $("#toolbox-heading").text(gettext("Powered by pretix"));
} else {
$("#toolbox-heading").text(gettext("Object"));
}
@@ -415,6 +470,22 @@ var editor = {
return text;
},
+ _add_poweredby: function (content) {
+ var rect = new fabric.Poweredby({
+ left: 100,
+ top: 100,
+ width: 205,
+ height: 126,
+ lockRotation: true,
+ lockUniScaling: true,
+ content: content
+ });
+ rect.setControlsVisibility({'mtr': false});
+ editor.fabric.add(rect);
+ editor._create_savepoint();
+ return rect;
+ },
+
_add_qrcode: function () {
var rect = new fabric.Barcodearea({
left: 100,
@@ -654,6 +725,7 @@ var editor = {
editor._load_pdf();
$("#editor-add-qrcode, #editor-add-qrcode-lead").click(editor._add_qrcode);
$("#editor-add-text").click(editor._add_text);
+ $("#editor-add-poweredby").click(function() {editor._add_poweredby("dark")});
editor.$cva.get(0).tabIndex = 1000;
editor.$cva.on("keydown", editor._on_keydown);
$("#editor-save").on("click", editor._save);
diff --git a/src/pretix/static/pretixcontrol/scss/pdfeditor.css b/src/pretix/static/pretixcontrol/scss/pdfeditor.css
index 5c40fef5e6..0d499a2e1f 100644
--- a/src/pretix/static/pretixcontrol/scss/pdfeditor.css
+++ b/src/pretix/static/pretixcontrol/scss/pdfeditor.css
@@ -13,10 +13,19 @@ body {
#toolbox .control-group {
margin-bottom: 5px;
}
-#toolbox .position, #toolbox .squaresize, #toolbox[data-type] .pdf-info, #toolbox .text, #toolbox .object-buttons {
+#toolbox .position,
+#toolbox .squaresize,
+#toolbox .poweredby,
+#toolbox[data-type] .pdf-info,
+#toolbox .text,
+#toolbox .object-buttons {
display: none;
}
-#toolbox[data-type] .position, #toolbox[data-type=barcodearea] .squaresize, #toolbox[data-type=text] .text, #toolbox[data-type=textarea] .text,
+#toolbox[data-type] .position,
+#toolbox[data-type=barcodearea] .squaresize,
+#toolbox[data-type=poweredby] .poweredby,
+#toolbox[data-type=text] .text,
+#toolbox[data-type=textarea] .text,
#toolbox[data-type] .object-buttons {
display: block;
}
diff --git a/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.png b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.png
new file mode 100644
index 0000000000..e244e4de1a
Binary files /dev/null and b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.png differ
diff --git a/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.svg b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.svg
new file mode 100644
index 0000000000..4a7da8e011
--- /dev/null
+++ b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_dark.svg
@@ -0,0 +1,89 @@
+
+
+
+
diff --git a/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.png b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.png
new file mode 100644
index 0000000000..d05c47565d
Binary files /dev/null and b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.png differ
diff --git a/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.svg b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.svg
new file mode 100644
index 0000000000..76066bdc61
--- /dev/null
+++ b/src/pretix/static/pretixpresale/pdf/powered_by_pretix_white.svg
@@ -0,0 +1,92 @@
+
+
+
+
diff --git a/src/pretix/static/pretixpresale/pdf/ticket_default_a4.pdf b/src/pretix/static/pretixpresale/pdf/ticket_default_a4.pdf
index 2ac04cf1d6..820cab02df 100644
Binary files a/src/pretix/static/pretixpresale/pdf/ticket_default_a4.pdf and b/src/pretix/static/pretixpresale/pdf/ticket_default_a4.pdf differ
diff --git a/src/pretix/static/pretixpresale/pdf/ticket_default_a4.svg b/src/pretix/static/pretixpresale/pdf/ticket_default_a4.svg
index d9a9d1359f..1a68a2b03f 100644
--- a/src/pretix/static/pretixpresale/pdf/ticket_default_a4.svg
+++ b/src/pretix/static/pretixpresale/pdf/ticket_default_a4.svg
@@ -14,7 +14,7 @@
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
- inkscape:version="0.92.1 r"
+ inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="ticket_default_a4.svg">