diff --git a/src/pretix/base/invoicing/pdf.py b/src/pretix/base/invoicing/pdf.py
index 21765a629..efa3a0280 100644
--- a/src/pretix/base/invoicing/pdf.py
+++ b/src/pretix/base/invoicing/pdf.py
@@ -22,9 +22,7 @@
import datetime
import logging
import math
-import re
import textwrap
-import unicodedata
from collections import defaultdict
from decimal import Decimal
from io import BytesIO
@@ -58,8 +56,8 @@ from pretix.base.services.currencies import SOURCE_NAMES
from pretix.base.signals import register_invoice_renderers
from pretix.base.templatetags.money import money_filter
from pretix.helpers.reportlab import (
- FontFallbackParagraph, ThumbnailingImageReader, register_ttf_font_if_new,
- reshaper,
+ FontFallbackParagraph, PlainTextParagraph, ThumbnailingImageReader,
+ normalize_text, register_ttf_font_if_new, reshaper,
)
from pretix.presale.style import get_fonts
@@ -259,18 +257,8 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
register_ttf_font_if_new(family + ' B I', finders.find(styles['bolditalic']['truetype']))
def _normalize(self, text):
- # reportlab does not support unicode combination characters
- # It's important we do this before we use ArabicReshaper
- text = unicodedata.normalize("NFKC", text)
-
- # reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper
- # to resolve all ligatures and python-bidi to switch RTL texts.
- try:
- text = "
".join(get_display(reshaper.reshape(l)) for l in re.split("
", text))
- except:
- logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
-
- return text
+ # alias kept for plugin compatibility
+ return normalize_text(text)
def _upper(self, val):
# We uppercase labels, but not in every language
@@ -351,10 +339,15 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
return 'invoice.pdf', 'application/pdf', buffer.read()
def _clean_text(self, text, tags=None):
- return self._normalize(bleach.clean(
- text,
- tags=set(tags) if tags else set()
- ).strip().replace('
', '
').replace('\n', '
\n'))
+ # For backwards compatibility with customer content, we need to support tags like
and in a few text
+ # fields. Therefore, we can't use PlainTextParagraph for these, but run bleach instead to limit the allowed
+ # tags.
+ return self._normalize(
+ bleach.clean(
+ text,
+ tags=set(tags) if tags else set()
+ ).strip().replace('
', '
').replace('\n', '
\n')
+ )
class PaidMarker(Flowable):
@@ -405,8 +398,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
invoice_to_top = 52 * mm
def _draw_invoice_to(self, canvas):
- p = FontFallbackParagraph(self._clean_text(self.invoice.address_invoice_to),
- style=self.stylesheet['Normal'])
+ p = PlainTextParagraph(self.invoice.address_invoice_to, style=self.stylesheet['Normal'])
p.wrapOn(canvas, self.invoice_to_width, self.invoice_to_height)
p_size = p.wrap(self.invoice_to_width, self.invoice_to_height)
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - p_size[1] - self.invoice_to_top)
@@ -417,8 +409,8 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
invoice_from_top = 17 * mm
def _draw_invoice_from(self, canvas):
- p = FontFallbackParagraph(
- self._clean_text(self.invoice.full_invoice_from),
+ p = PlainTextParagraph(
+ self.invoice.full_invoice_from,
style=self.stylesheet['InvoiceFrom']
)
p.wrapOn(canvas, self.invoice_from_width, self.invoice_from_height)
@@ -548,13 +540,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
def _draw_event(self, canvas):
def shorten(txt):
txt = str(txt)
- txt = bleach.clean(txt, tags=set()).strip()
- p = FontFallbackParagraph(self._normalize(txt.strip().replace('\n', '
\n')), style=self.stylesheet['Normal'])
+ p = PlainTextParagraph(txt, style=self.stylesheet['Normal'])
p_size = p.wrap(self.event_width, self.event_height)
while p_size[1] > 2 * self.stylesheet['Normal'].leading:
txt = ' '.join(txt.replace('…', '').split()[:-1]) + '…'
- p = FontFallbackParagraph(self._normalize(txt.strip().replace('\n', '
\n')), style=self.stylesheet['Normal'])
+ p = PlainTextParagraph(txt, style=self.stylesheet['Normal'])
p_size = p.wrap(self.event_width, self.event_height)
return txt
@@ -572,7 +563,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
else:
p_str = shorten(self.invoice.event.name)
- p = FontFallbackParagraph(self._normalize(p_str.strip().replace('\n', '
\n')), style=self.stylesheet['Normal'])
+ p = PlainTextParagraph(p_str, style=self.stylesheet['Normal'])
p.wrapOn(canvas, self.event_width, self.event_height)
p_size = p.wrap(self.event_width, self.event_height)
p.drawOn(canvas, self.event_left, self.pagesize[1] - self.event_top - p_size[1])
@@ -645,39 +636,37 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
type_info_text = self.invoice.transmission_type_instance.pdf_info_text()
if type_info_text:
- story.append(FontFallbackParagraph(
+ story.append(PlainTextParagraph(
type_info_text,
self.stylesheet['WarningBlock']
))
if self.invoice.custom_field:
- story.append(FontFallbackParagraph(
+ story.append(PlainTextParagraph(
'{}: {}'.format(
- self._clean_text(str(self.invoice.event.settings.invoice_address_custom_field)),
- self._clean_text(self.invoice.custom_field),
+ str(self.invoice.event.settings.invoice_address_custom_field),
+ self.invoice.custom_field,
),
self.stylesheet['Normal']
))
if self.invoice.internal_reference:
- story.append(FontFallbackParagraph(
- self._normalize(pgettext('invoice', 'Customer reference: {reference}').format(
- reference=self._clean_text(self.invoice.internal_reference),
- )),
+ story.append(PlainTextParagraph(
+ pgettext('invoice', 'Customer reference: {reference}').format(
+ reference=self.invoice.internal_reference,
+ ),
self.stylesheet['Normal']
))
if self.invoice.invoice_to_vat_id:
- story.append(FontFallbackParagraph(
- self._normalize(pgettext('invoice', 'Customer VAT ID')) + ': ' +
- self._clean_text(self.invoice.invoice_to_vat_id),
+ story.append(PlainTextParagraph(
+ pgettext('invoice', 'Customer VAT ID') + ': ' + self.invoice.invoice_to_vat_id,
self.stylesheet['Normal']
))
if self.invoice.invoice_to_beneficiary:
- story.append(FontFallbackParagraph(
- self._normalize(pgettext('invoice', 'Beneficiary')) + ':
' +
- self._clean_text(self.invoice.invoice_to_beneficiary),
+ story.append(PlainTextParagraph(
+ pgettext('invoice', 'Beneficiary') + ':\n' + self.invoice.invoice_to_beneficiary,
self.stylesheet['Normal']
))
@@ -707,11 +696,11 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
story = [
NextPageTemplate('FirstPage'),
- FontFallbackParagraph(
- self._normalize(
+ PlainTextParagraph(
+ (
pgettext('invoice', 'Tax Invoice') if str(self.invoice.invoice_from_country) == 'AU'
else pgettext('invoice', 'Invoice')
- ) if not self.invoice.is_cancellation else self._normalize(pgettext('invoice', 'Cancellation')),
+ ) if not self.invoice.is_cancellation else pgettext('invoice', 'Cancellation'),
self.stylesheet['Heading1']
),
Spacer(1, 5 * mm),
@@ -733,17 +722,17 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
]
if has_taxes:
tdata = [(
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Description')), self.stylesheet['Bold']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Qty')), self.stylesheet['BoldRightNoSplit']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax rate')), self.stylesheet['BoldRightNoSplit']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Net')), self.stylesheet['BoldRightNoSplit']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Gross')), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Description'), self.stylesheet['Bold']),
+ PlainTextParagraph(pgettext('invoice', 'Qty'), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Tax rate'), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Net'), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Gross'), self.stylesheet['BoldRightNoSplit']),
)]
else:
tdata = [(
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Description')), self.stylesheet['Bold']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Qty')), self.stylesheet['BoldRightNoSplit']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Amount')), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Description'), self.stylesheet['Bold']),
+ PlainTextParagraph(pgettext('invoice', 'Qty'), self.stylesheet['BoldRightNoSplit']),
+ PlainTextParagraph(pgettext('invoice', 'Amount'), self.stylesheet['BoldRightNoSplit']),
)]
def _group_key(line):
@@ -780,8 +769,8 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
max_height = self.stylesheet['Normal'].leading * 5
p_style = self.stylesheet['Normal']
for __ in range(1000):
- p = FontFallbackParagraph(
- self._clean_text(curr_description, tags=['br']),
+ p = PlainTextParagraph(
+ curr_description,
p_style
)
h = p.wrap(max_width, doc.height)[1]
@@ -862,7 +851,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
# Group together at the end of the invoice
request_show_service_date = period_line
elif period_line:
- description_p_list.append(FontFallbackParagraph(
+ description_p_list.append(PlainTextParagraph(
period_line,
self.stylesheet['Fineprint']
))
@@ -874,7 +863,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
net_price=money_filter(net_value, self.invoice.event.currency),
gross_price=money_filter(gross_value, self.invoice.event.currency),
)
- description_p_list.append(FontFallbackParagraph(
+ description_p_list.append(PlainTextParagraph(
single_price_line,
self.stylesheet['Fineprint']
))
@@ -883,11 +872,11 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
description_p_list.pop(0),
str(len(lines)),
localize(tax_rate) + " %",
- FontFallbackParagraph(
+ PlainTextParagraph(
money_filter(net_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
self.stylesheet['NormalRight']
),
- FontFallbackParagraph(
+ PlainTextParagraph(
money_filter(gross_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
self.stylesheet['NormalRight']
),
@@ -904,14 +893,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
single_price_line = pgettext('invoice', 'Single price: {price}').format(
price=money_filter(gross_value, self.invoice.event.currency),
)
- description_p_list.append(FontFallbackParagraph(
+ description_p_list.append(PlainTextParagraph(
single_price_line,
self.stylesheet['Fineprint']
))
tdata.append((
description_p_list.pop(0),
str(len(lines)),
- FontFallbackParagraph(
+ PlainTextParagraph(
money_filter(gross_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
self.stylesheet['NormalRight']
),
@@ -944,12 +933,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
if has_taxes:
tdata.append([
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '', '', '',
+ PlainTextParagraph(pgettext('invoice', 'Invoice total'), self.stylesheet['Bold']), '', '', '',
money_filter(total, self.invoice.event.currency)
])
else:
tdata.append([
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '',
+ PlainTextParagraph(pgettext('invoice', 'Invoice total'), self.stylesheet['Bold']), '',
money_filter(total, self.invoice.event.currency)
])
@@ -958,12 +947,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
pending_sum = self.invoice.order.pending_sum
if pending_sum != total:
tdata.append(
- [FontFallbackParagraph(self._normalize(pgettext('invoice', 'Received payments')), self.stylesheet['Normal'])] +
+ [PlainTextParagraph(pgettext('invoice', 'Received payments'), self.stylesheet['Normal'])] +
(['', '', ''] if has_taxes else ['']) +
[money_filter(pending_sum - total, self.invoice.event.currency)]
)
tdata.append(
- [FontFallbackParagraph(self._normalize(pgettext('invoice', 'Outstanding payments')), self.stylesheet['Bold'])] +
+ [PlainTextParagraph(pgettext('invoice', 'Outstanding payments'), self.stylesheet['Bold'])] +
(['', '', ''] if has_taxes else ['']) +
[money_filter(pending_sum, self.invoice.event.currency)]
)
@@ -980,12 +969,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
s=Sum('amount')
)['s'] or Decimal('0.00')
tdata.append(
- [FontFallbackParagraph(self._normalize(pgettext('invoice', 'Paid by gift card')), self.stylesheet['Normal'])] +
+ [PlainTextParagraph(pgettext('invoice', 'Paid by gift card'), self.stylesheet['Normal'])] +
(['', '', ''] if has_taxes else ['']) +
[money_filter(giftcard_sum, self.invoice.event.currency)]
)
tdata.append(
- [FontFallbackParagraph(self._normalize(pgettext('invoice', 'Remaining amount')), self.stylesheet['Bold'])] +
+ [PlainTextParagraph(pgettext('invoice', 'Remaining amount'), self.stylesheet['Bold'])] +
(['', '', ''] if has_taxes else ['']) +
[money_filter(total - giftcard_sum, self.invoice.event.currency)]
)
@@ -1008,14 +997,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
story.append(Spacer(1, 10 * mm))
if request_show_service_date:
- story.append(FontFallbackParagraph(
- self._normalize(pgettext('invoice', 'Invoice period: {daterange}').format(daterange=request_show_service_date)),
+ story.append(PlainTextParagraph(
+ pgettext('invoice', 'Invoice period: {daterange}').format(daterange=request_show_service_date),
self.stylesheet['Normal']
))
if self.invoice.payment_provider_text:
story.append(FontFallbackParagraph(
- self._normalize(self.invoice.payment_provider_text),
+ self._clean_text(self.invoice.payment_provider_text, tags=['br', 'b']),
self.stylesheet['Normal']
))
@@ -1039,10 +1028,10 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
('FONTNAME', (0, 0), (-1, -1), self.font_regular),
]
thead = [
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax rate')), self.stylesheet['Fineprint']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Net value')), self.stylesheet['FineprintRight']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Gross value')), self.stylesheet['FineprintRight']),
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax')), self.stylesheet['FineprintRight']),
+ PlainTextParagraph(pgettext('invoice', 'Tax rate'), self.stylesheet['Fineprint']),
+ PlainTextParagraph(pgettext('invoice', 'Net value'), self.stylesheet['FineprintRight']),
+ PlainTextParagraph(pgettext('invoice', 'Gross value'), self.stylesheet['FineprintRight']),
+ PlainTextParagraph(pgettext('invoice', 'Tax'), self.stylesheet['FineprintRight']),
''
]
tdata = [thead]
@@ -1053,7 +1042,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
continue
tax = taxvalue_map[idx]
tdata.append([
- FontFallbackParagraph(self._normalize(localize(rate) + " % " + name), self.stylesheet['Fineprint']),
+ PlainTextParagraph(localize(rate) + " % " + name, self.stylesheet['Fineprint']),
money_filter(gross - tax, self.invoice.event.currency),
money_filter(gross, self.invoice.event.currency),
money_filter(tax, self.invoice.event.currency),
@@ -1072,7 +1061,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
table.setStyle(TableStyle(tstyledata))
story.append(Spacer(5 * mm, 5 * mm))
story.append(KeepTogether([
- FontFallbackParagraph(self._normalize(pgettext('invoice', 'Included taxes')), self.stylesheet['FineprintHeading']),
+ PlainTextParagraph(pgettext('invoice', 'Included taxes'), self.stylesheet['FineprintHeading']),
table
]))
@@ -1089,7 +1078,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
net = gross - tax
tdata.append([
- FontFallbackParagraph(self._normalize(localize(rate) + " % " + name), self.stylesheet['Fineprint']),
+ PlainTextParagraph(localize(rate) + " % " + name, self.stylesheet['Fineprint']),
fmt(net), fmt(gross), fmt(tax), ''
])
@@ -1098,13 +1087,13 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
story.append(KeepTogether([
Spacer(1, height=2 * mm),
- FontFallbackParagraph(
- self._normalize(pgettext(
+ PlainTextParagraph(
+ pgettext(
'invoice', 'Using the conversion rate of 1:{rate} as published by the {authority} on '
'{date}, this corresponds to:'
).format(rate=localize(self.invoice.foreign_currency_rate),
authority=SOURCE_NAMES.get(self.invoice.foreign_currency_source, "?"),
- date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT"))),
+ date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT")),
self.stylesheet['Fineprint']
),
Spacer(1, height=3 * mm),
@@ -1113,14 +1102,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
elif self.invoice.foreign_currency_display and self.invoice.foreign_currency_rate:
foreign_total = round_decimal(total * self.invoice.foreign_currency_rate)
story.append(Spacer(1, 5 * mm))
- story.append(FontFallbackParagraph(self._normalize(
+ story.append(PlainTextParagraph(
pgettext(
'invoice', 'Using the conversion rate of 1:{rate} as published by the {authority} on '
'{date}, the invoice total corresponds to {total}.'
).format(rate=localize(self.invoice.foreign_currency_rate),
date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT"),
authority=SOURCE_NAMES.get(self.invoice.foreign_currency_source, "?"),
- total=fmt(foreign_total))),
+ total=fmt(foreign_total)),
self.stylesheet['Fineprint']
))
@@ -1162,11 +1151,8 @@ class Modern1Renderer(ClassicInvoiceRenderer):
def _draw_invoice_from(self, canvas):
if not self.invoice.invoice_from:
return
- c = [
- self._clean_text(l)
- for l in self.invoice.address_invoice_from.strip().split('\n')
- ]
- p = FontFallbackParagraph(self._normalize(' · '.join(c)), style=self.stylesheet['Sender'])
+ c = self.invoice.address_invoice_from.strip().split('\n')
+ p = PlainTextParagraph(' · '.join(c), style=self.stylesheet['Sender'])
p.wrapOn(canvas, self.invoice_to_width, 15.7 * mm)
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - self.invoice_to_top + 2 * mm)
super()._draw_invoice_from(canvas)
@@ -1225,8 +1211,8 @@ class Modern1Renderer(ClassicInvoiceRenderer):
_draw(pgettext('invoice', 'Order code'), self.invoice.order.full_code, value_size, self.left_margin, 45 * mm, **kwargs)
]
- p = FontFallbackParagraph(
- self._normalize(date_format(self.invoice.date, "DATE_FORMAT")),
+ p = PlainTextParagraph(
+ date_format(self.invoice.date, "DATE_FORMAT"),
style=ParagraphStyle(name=f'Normal{value_size}', fontName=self.font_regular, fontSize=value_size, leading=value_size * 1.2)
)
w = stringWidth(p.text, p.frags[0].fontName, p.frags[0].fontSize)
@@ -1283,7 +1269,7 @@ class Modern1SimplifiedRenderer(Modern1Renderer):
i = []
if not self.invoice.event.has_subevents and self.invoice.event.settings.show_dates_on_frontpage:
- i.append(FontFallbackParagraph(
+ i.append(PlainTextParagraph(
pgettext('invoice', 'Event date: {date_range}').format(
date_range=self.invoice.event.get_date_range_display(),
),
diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py
index 5d11c3504..e8388276b 100644
--- a/src/pretix/base/pdf.py
+++ b/src/pretix/base/pdf.py
@@ -1045,7 +1045,7 @@ class Renderer:
except:
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
- p = Paragraph(text, style=style)
+ p = Paragraph(text, style=style) # not using AutoEscapeParagraph is safe as we escape above
return p, ad, lineheight
def _draw_textcontainer(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
diff --git a/src/pretix/control/sysreport.py b/src/pretix/control/sysreport.py
index 6beb0e4fc..e2a908cb0 100644
--- a/src/pretix/control/sysreport.py
+++ b/src/pretix/control/sysreport.py
@@ -38,6 +38,7 @@ from pretix import __version__
from pretix.base.models import Order, OrderPayment, Transaction
from pretix.base.plugins import get_all_plugins
from pretix.base.templatetags.money import money_filter
+from pretix.helpers.reportlab import PlainTextParagraph
from pretix.plugins.reports.exporters import ReportlabExportMixin
from pretix.settings import DATA_DIR
@@ -79,23 +80,23 @@ class SysReport(ReportlabExportMixin):
style_small.fontSize = 6
story = [
- Paragraph("System report", headlinestyle),
+ PlainTextParagraph("System report", headlinestyle),
Spacer(1, 5 * mm),
- Paragraph("Usage", subheadlinestyle),
+ PlainTextParagraph("Usage", subheadlinestyle),
Spacer(1, 5 * mm),
self._usage_table(),
Spacer(1, 5 * mm),
- Paragraph("Installed versions", subheadlinestyle),
+ PlainTextParagraph("Installed versions", subheadlinestyle),
Spacer(1, 5 * mm),
self._tech_table(),
Spacer(1, 5 * mm),
- Paragraph("Plugins", subheadlinestyle),
+ PlainTextParagraph("Plugins", subheadlinestyle),
Spacer(1, 5 * mm),
- Paragraph(self._get_plugin_versions(), style_small),
+ PlainTextParagraph(self._get_plugin_versions(), style_small),
Spacer(1, 5 * mm),
- Paragraph("Custom templates", subheadlinestyle),
+ PlainTextParagraph("Custom templates", subheadlinestyle),
Spacer(1, 5 * mm),
- Paragraph(self._get_custom_templates(), style_small),
+ PlainTextParagraph(self._get_custom_templates(), style_small),
Spacer(1, 5 * mm),
]
@@ -121,13 +122,13 @@ class SysReport(ReportlabExportMixin):
("RIGHTPADDING", (-1, 0), (-1, -1), 0),
]
tdata = [
- [Paragraph("Site URL:", style), Paragraph(settings.SITE_URL, style)],
- [Paragraph("pretix version:", style), Paragraph(__version__, style)],
- [Paragraph("Python version:", style), Paragraph(sys.version, style)],
- [Paragraph("Platform:", style), Paragraph(platform.platform(), style)],
+ [PlainTextParagraph("Site URL:", style), Paragraph(settings.SITE_URL, style)],
+ [PlainTextParagraph("pretix version:", style), Paragraph(__version__, style)],
+ [PlainTextParagraph("Python version:", style), Paragraph(sys.version, style)],
+ [PlainTextParagraph("Platform:", style), Paragraph(platform.platform(), style)],
[
- Paragraph("Database engine:", style),
- Paragraph(settings.DATABASES["default"]["ENGINE"], style),
+ PlainTextParagraph("Database engine:", style),
+ PlainTextParagraph(settings.DATABASES["default"]["ENGINE"], style),
],
]
table = Table(tdata, colWidths=colwidths, repeatRows=0)
@@ -206,7 +207,7 @@ class SysReport(ReportlabExportMixin):
year_last = now().year
tdata = [
[
- Paragraph(l, style_small_head)
+ PlainTextParagraph(l, style_small_head)
for l in (
"Time frame",
"Currency",
@@ -257,19 +258,19 @@ class SysReport(ReportlabExportMixin):
tdata.append(
(
- Paragraph(
+ PlainTextParagraph(
date_format(first_day, "M Y")
+ " – "
+ date_format(after_day - timedelta(days=1), "M Y"),
style_small,
),
- Paragraph(c, style_small),
- Paragraph(str(orders_count), style_small) if i == 0 else "",
- Paragraph(money_filter(revenue_data.get("s_net") or 0, c), style_small),
- Paragraph(str(testmode_count), style_small) if i == 0 else "",
- Paragraph(str(unconfirmed_count), style_small) if i == 0 else "",
- Paragraph(str(revenue_data.get("c") or 0), style_small),
- Paragraph(money_filter(revenue_data.get("s_gross") or 0, c), style_small),
+ PlainTextParagraph(c, style_small),
+ PlainTextParagraph(str(orders_count), style_small) if i == 0 else "",
+ PlainTextParagraph(money_filter(revenue_data.get("s_net") or 0, c), style_small),
+ PlainTextParagraph(str(testmode_count), style_small) if i == 0 else "",
+ PlainTextParagraph(str(unconfirmed_count), style_small) if i == 0 else "",
+ PlainTextParagraph(str(revenue_data.get("c") or 0), style_small),
+ PlainTextParagraph(money_filter(revenue_data.get("s_gross") or 0, c), style_small),
)
)
diff --git a/src/pretix/helpers/reportlab.py b/src/pretix/helpers/reportlab.py
index 5a39ac4a5..618dbb87e 100644
--- a/src/pretix/helpers/reportlab.py
+++ b/src/pretix/helpers/reportlab.py
@@ -20,14 +20,19 @@
# .
#
import logging
+import re
+import unicodedata
from arabic_reshaper import ArabicReshaper
+from bidi import get_display
from django.conf import settings
from django.utils.functional import SimpleLazyObject
+from django.utils.html import escape
from PIL import Image
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.utils import ImageReader
from reportlab.pdfbase import pdfmetrics
+from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Paragraph
from pretix.presale.style import get_fonts
@@ -70,6 +75,20 @@ reshaper = SimpleLazyObject(lambda: ArabicReshaper(configuration={
}))
+def normalize_text(text: str) -> str:
+ # reportlab does not support unicode combination characters
+ # It's important we do this before we use ArabicReshaper
+ text = unicodedata.normalize("NFKC", text)
+
+ # reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper
+ # to resolve all ligatures and python-bidi to switch RTL texts.
+ try:
+ text = "\n".join(get_display(reshaper.reshape(l)) for l in re.split("\n", text))
+ except:
+ logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
+ return text
+
+
class FontFallbackParagraph(Paragraph):
def __init__(self, text, style=None, *args, **kwargs):
if style is None:
@@ -87,6 +106,8 @@ class FontFallbackParagraph(Paragraph):
if not text:
return True
font = pdfmetrics.getFont(font_name)
+ if not isinstance(font, TTFont):
+ return True
return all(
ord(c) in font.face.charToGlyph or not c.isprintable()
for c in text
@@ -102,6 +123,24 @@ class FontFallbackParagraph(Paragraph):
return family
+class PlainTextParagraph(FontFallbackParagraph):
+ def __init__(self, text, style=None, linebreaks=True, *args, **kwargs):
+ if not isinstance(text, str):
+ if hasattr(text, '__html__'):
+ raise ValueError("It is contradictory to pass escaped content to PlainTextParagraph")
+ text = str(text)
+
+ # Normalize unicode and apply reshaping
+ text = normalize_text(text)
+
+ # Escape any HTML in the text
+ text = escape(text)
+
+ if linebreaks:
+ text = text.strip().replace("\n", "
\n")
+ super().__init__(text, style, *args, **kwargs)
+
+
def register_ttf_font_if_new(name, path):
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
diff --git a/src/pretix/plugins/checkinlists/exporters.py b/src/pretix/plugins/checkinlists/exporters.py
index 21739e104..c12807f6b 100644
--- a/src/pretix/plugins/checkinlists/exporters.py
+++ b/src/pretix/plugins/checkinlists/exporters.py
@@ -64,7 +64,7 @@ from pretix.base.timeframes import (
from pretix.control.forms.widgets import Select2
from pretix.helpers.filenames import safe_for_filename
from pretix.helpers.iter import chunked_iterable
-from pretix.helpers.reportlab import FontFallbackParagraph
+from pretix.helpers.reportlab import PlainTextParagraph
from pretix.helpers.templatetags.jsonfield import JSONExtract
from pretix.plugins.reports.exporters import ReportlabExportMixin
@@ -344,7 +344,7 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
]
story = [
- FontFallbackParagraph(
+ PlainTextParagraph(
cl.name,
headlinestyle
),
@@ -352,7 +352,7 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
if cl.subevent:
story += [
Spacer(1, 3 * mm),
- FontFallbackParagraph(
+ PlainTextParagraph(
'{} ({} {})'.format(
cl.subevent.name,
cl.subevent.get_date_range_display(),
@@ -382,10 +382,10 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
headrowstyle.fontName = 'OpenSansBd'
for q in questions:
txt = str(q.question)
- p = FontFallbackParagraph(txt, headrowstyle)
+ p = PlainTextParagraph(txt, headrowstyle)
while p.wrap(colwidths[len(tdata[0])], 5000)[1] > 30 * mm:
txt = txt[:len(txt) - 50] + "..."
- p = FontFallbackParagraph(txt, headrowstyle)
+ p = PlainTextParagraph(txt, headrowstyle)
tdata[0].append(p)
qs = self._get_queryset(cl, form_data)
@@ -432,8 +432,8 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
CBFlowable(bool(op.last_checked_in)) if not op.blocked else '—',
'✘' if op.order.status != Order.STATUS_PAID else '✔',
op.order.code,
- FontFallbackParagraph(name, self.get_style()),
- FontFallbackParagraph(bleach.clean(str(item), tags={'br'}).strip().replace('
', '
'), self.get_style()),
+ PlainTextParagraph(name, self.get_style()),
+ PlainTextParagraph(bleach.clean(str(item), tags={'br'}).strip().replace('
', '
'), self.get_style()),
]
acache = {}
if op.addon_to:
@@ -444,10 +444,10 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
for q in questions:
txt = acache.get(q.pk, '')
txt = bleach.clean(txt, tags={'br'}).strip().replace('
', '
')
- p = FontFallbackParagraph(txt, self.get_style())
+ p = PlainTextParagraph(txt, self.get_style())
while p.wrap(colwidths[len(row)], 5000)[1] > 50 * mm:
txt = txt[:len(txt) - 50] + "..."
- p = FontFallbackParagraph(txt, self.get_style())
+ p = PlainTextParagraph(txt, self.get_style())
row.append(p)
if op.order.status != Order.STATUS_PAID:
tstyledata += [
diff --git a/src/pretix/plugins/reports/accountingreport.py b/src/pretix/plugins/reports/accountingreport.py
index 17315eb02..6c09ad141 100644
--- a/src/pretix/plugins/reports/accountingreport.py
+++ b/src/pretix/plugins/reports/accountingreport.py
@@ -36,7 +36,7 @@ from reportlab.lib import colors, pagesizes
from reportlab.lib.enums import TA_CENTER, TA_RIGHT
from reportlab.lib.units import mm
from reportlab.platypus import (
- KeepTogether, PageTemplate, Paragraph, Spacer, Table, TableStyle,
+ KeepTogether, PageTemplate, Spacer, Table, TableStyle,
)
from pretix.base.exporter import BaseExporter
@@ -49,7 +49,7 @@ from pretix.base.timeframes import (
resolve_timeframe_to_datetime_start_inclusive_end_exclusive,
)
from pretix.control.forms.filter import get_all_payment_providers
-from pretix.helpers.reportlab import FontFallbackParagraph
+from pretix.helpers.reportlab import PlainTextParagraph
from pretix.plugins.reports.exporters import ReportlabExportMixin
@@ -311,13 +311,13 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
tdata = [
[
- FontFallbackParagraph(self._transaction_group_header_label(), tstyle_bold),
- FontFallbackParagraph(_("Price"), tstyle_bold_right),
- FontFallbackParagraph(_("Tax rate"), tstyle_bold_right),
- FontFallbackParagraph("#", tstyle_bold_right),
- FontFallbackParagraph(_("Net total"), tstyle_bold_right),
- FontFallbackParagraph(_("Tax total"), tstyle_bold_right),
- FontFallbackParagraph(_("Gross total"), tstyle_bold_right),
+ PlainTextParagraph(self._transaction_group_header_label(), tstyle_bold),
+ PlainTextParagraph(_("Price"), tstyle_bold_right),
+ PlainTextParagraph(_("Tax rate"), tstyle_bold_right),
+ PlainTextParagraph("#", tstyle_bold_right),
+ PlainTextParagraph(_("Net total"), tstyle_bold_right),
+ PlainTextParagraph(_("Tax total"), tstyle_bold_right),
+ PlainTextParagraph(_("Gross total"), tstyle_bold_right),
]
]
@@ -347,12 +347,12 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
if e != last_group:
if last_group_head_idx > 0 and e is not None:
- tdata[last_group_head_idx][4] = Paragraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
- tdata[last_group_head_idx][5] = Paragraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
- tdata[last_group_head_idx][6] = Paragraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][4] = PlainTextParagraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][5] = PlainTextParagraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][6] = PlainTextParagraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
tdata.append(
[
- FontFallbackParagraph(
+ PlainTextParagraph(
e,
tstyle_bold,
),
@@ -375,20 +375,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
text = self._transaction_row_label(r)
tdata.append(
[
- FontFallbackParagraph(text, tstyle),
- Paragraph(
+ PlainTextParagraph(text, tstyle),
+ PlainTextParagraph(
money_filter(r["price"], currency)
if "price" in r and r["price"] is not None
else "",
tstyle_right,
),
- Paragraph(localize(r["tax_rate"].normalize()) + " %", tstyle_right),
- Paragraph(str(r["sum_cont"]), tstyle_right),
- Paragraph(
+ PlainTextParagraph(localize(r["tax_rate"].normalize()) + " %", tstyle_right),
+ PlainTextParagraph(str(r["sum_cont"]), tstyle_right),
+ PlainTextParagraph(
money_filter(r["sum_price"] - r["sum_tax"], currency), tstyle_right
),
- Paragraph(money_filter(r["sum_tax"], currency), tstyle_right),
- Paragraph(money_filter(r["sum_price"], currency), tstyle_right),
+ PlainTextParagraph(money_filter(r["sum_tax"], currency), tstyle_right),
+ PlainTextParagraph(money_filter(r["sum_price"], currency), tstyle_right),
]
)
sum_cnt_by_tax_rate[r["tax_rate"]] += r["sum_cont"]
@@ -398,19 +398,19 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
sum_tax_by_group += r["sum_tax"]
if last_group_head_idx > 0 and last_group is not None:
- tdata[last_group_head_idx][4] = Paragraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
- tdata[last_group_head_idx][5] = Paragraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
- tdata[last_group_head_idx][6] = Paragraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][4] = PlainTextParagraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][5] = PlainTextParagraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
+ tdata[last_group_head_idx][6] = PlainTextParagraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
if len(sum_tax_by_tax_rate) > 1:
for tax_rate in sorted(sum_tax_by_tax_rate.keys(), reverse=True):
tdata.append(
[
- FontFallbackParagraph(_("Sum"), tstyle),
- Paragraph("", tstyle_right),
- Paragraph(localize(tax_rate.normalize()) + " %", tstyle_right),
- Paragraph("", tstyle_right),
- Paragraph(
+ PlainTextParagraph(_("Sum"), tstyle),
+ PlainTextParagraph("", tstyle_right),
+ PlainTextParagraph(localize(tax_rate.normalize()) + " %", tstyle_right),
+ PlainTextParagraph("", tstyle_right),
+ PlainTextParagraph(
money_filter(
sum_price_by_tax_rate[tax_rate]
- sum_tax_by_tax_rate[tax_rate],
@@ -418,10 +418,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
),
tstyle_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(sum_tax_by_tax_rate[tax_rate], currency), tstyle_right
),
- Paragraph(
+ PlainTextParagraph(
money_filter(sum_price_by_tax_rate[tax_rate], currency),
tstyle_right,
),
@@ -439,11 +439,11 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
tdata.append(
[
- FontFallbackParagraph(_("Sum"), tstyle_bold),
- Paragraph("", tstyle_right),
- Paragraph("", tstyle_right),
- Paragraph("", tstyle_bold_right),
- Paragraph(
+ PlainTextParagraph(_("Sum"), tstyle_bold),
+ PlainTextParagraph("", tstyle_right),
+ PlainTextParagraph("", tstyle_right),
+ PlainTextParagraph("", tstyle_bold_right),
+ PlainTextParagraph(
money_filter(
sum(sum_price_by_tax_rate.values())
- sum(sum_tax_by_tax_rate.values()),
@@ -451,11 +451,11 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
),
tstyle_bold_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(sum(sum_tax_by_tax_rate.values()), currency),
tstyle_bold_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(sum(sum_price_by_tax_rate.values()), currency),
tstyle_bold_right,
),
@@ -493,10 +493,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
tdata = [
[
- FontFallbackParagraph(_("Payment method"), tstyle_bold),
- FontFallbackParagraph(_("Payments"), tstyle_bold_right),
- FontFallbackParagraph(_("Refunds"), tstyle_bold_right),
- FontFallbackParagraph(_("Total"), tstyle_bold_right),
+ PlainTextParagraph(_("Payment method"), tstyle_bold),
+ PlainTextParagraph(_("Payments"), tstyle_bold_right),
+ PlainTextParagraph(_("Refunds"), tstyle_bold_right),
+ PlainTextParagraph(_("Total"), tstyle_bold_right),
]
]
@@ -537,20 +537,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
for p in providers:
tdata.append(
[
- Paragraph(provider_names.get(p, p), tstyle),
- FontFallbackParagraph(
+ PlainTextParagraph(provider_names.get(p, p), tstyle),
+ PlainTextParagraph(
money_filter(payments_by_provider[p], currency)
if p in payments_by_provider
else "",
tstyle_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(refunds_by_provider[p], currency)
if p in refunds_by_provider
else "",
tstyle_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(
payments_by_provider.get(p, Decimal("0.00"))
- refunds_by_provider.get(p, Decimal("0.00")),
@@ -563,20 +563,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
tdata.append(
[
- FontFallbackParagraph(_("Sum"), tstyle_bold),
- Paragraph(
+ PlainTextParagraph(_("Sum"), tstyle_bold),
+ PlainTextParagraph(
money_filter(
sum(payments_by_provider.values(), Decimal("0.00")), currency
),
tstyle_bold_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(
sum(refunds_by_provider.values(), Decimal("0.00")), currency
),
tstyle_bold_right,
),
- Paragraph(
+ PlainTextParagraph(
money_filter(
sum(payments_by_provider.values(), Decimal("0.00"))
- sum(refunds_by_provider.values(), Decimal("0.00")),
@@ -641,7 +641,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
open_before = tx_before - p_before + r_before
tdata.append(
[
- FontFallbackParagraph(
+ PlainTextParagraph(
_("Pending payments at {datetime}").format(
datetime=date_format(
(df_start - datetime.timedelta.resolution).astimezone(
@@ -653,7 +653,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
tstyle,
),
"",
- Paragraph(money_filter(open_before, currency), tstyle_right),
+ PlainTextParagraph(money_filter(open_before, currency), tstyle_right),
]
)
else:
@@ -670,30 +670,30 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
] or Decimal("0.00")
tdata.append(
[
- FontFallbackParagraph(_("Orders"), tstyle),
- Paragraph("+", tstyle_center),
- Paragraph(money_filter(tx_during, currency), tstyle_right),
+ PlainTextParagraph(_("Orders"), tstyle),
+ PlainTextParagraph("+", tstyle_center),
+ PlainTextParagraph(money_filter(tx_during, currency), tstyle_right),
]
)
tdata.append(
[
- FontFallbackParagraph(_("Payments"), tstyle),
- Paragraph("-", tstyle_center),
- Paragraph(money_filter(p_during, currency), tstyle_right),
+ PlainTextParagraph(_("Payments"), tstyle),
+ PlainTextParagraph("-", tstyle_center),
+ PlainTextParagraph(money_filter(p_during, currency), tstyle_right),
]
)
tdata.append(
[
- FontFallbackParagraph(_("Refunds"), tstyle),
- Paragraph("+", tstyle_center),
- Paragraph(money_filter(r_during, currency), tstyle_right),
+ PlainTextParagraph(_("Refunds"), tstyle),
+ PlainTextParagraph("+", tstyle_center),
+ PlainTextParagraph(money_filter(r_during, currency), tstyle_right),
]
)
open_after = open_before + tx_during - p_during + r_during
tdata.append(
[
- Paragraph(
+ PlainTextParagraph(
_("Pending payments at {datetime}").format(
datetime=date_format(
((df_end or now()) - datetime.timedelta.resolution).astimezone(
@@ -704,8 +704,8 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
),
tstyle_bold,
),
- Paragraph("=", tstyle_center),
- Paragraph(money_filter(open_after, currency), tstyle_bold_right),
+ PlainTextParagraph("=", tstyle_center),
+ PlainTextParagraph(money_filter(open_after, currency), tstyle_bold_right),
]
)
tstyledata += [
@@ -752,7 +752,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
)
tdata.append(
[
- Paragraph(
+ PlainTextParagraph(
_("Total gift card value at {datetime}").format(
datetime=date_format(
(df_start - datetime.timedelta.resolution).astimezone(
@@ -763,7 +763,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
),
tstyle,
),
- Paragraph(money_filter(tx_before, currency), tstyle_right),
+ PlainTextParagraph(money_filter(tx_before, currency), tstyle_right),
]
)
else:
@@ -774,8 +774,8 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
] or Decimal("0.00")
tdata.append(
[
- FontFallbackParagraph(_("Gift card transactions (credit)"), tstyle),
- Paragraph(money_filter(tx_during_pos, currency), tstyle_right),
+ PlainTextParagraph(_("Gift card transactions (credit)"), tstyle),
+ PlainTextParagraph(money_filter(tx_during_pos, currency), tstyle_right),
]
)
@@ -784,15 +784,15 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
] or Decimal("0.00")
tdata.append(
[
- FontFallbackParagraph(_("Gift card transactions (debit)"), tstyle),
- Paragraph(money_filter(tx_during_neg, currency), tstyle_right),
+ PlainTextParagraph(_("Gift card transactions (debit)"), tstyle),
+ PlainTextParagraph(money_filter(tx_during_neg, currency), tstyle_right),
]
)
open_after = tx_before + tx_during_pos + tx_during_neg
tdata.append(
[
- Paragraph(
+ PlainTextParagraph(
_("Total gift card value at {datetime}").format(
datetime=date_format(
((df_end or now()) - datetime.timedelta.resolution).astimezone(
@@ -803,7 +803,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
),
tstyle_bold,
),
- Paragraph(money_filter(open_after, currency), tstyle_bold_right),
+ PlainTextParagraph(money_filter(open_after, currency), tstyle_bold_right),
]
)
tstyledata += [
@@ -854,10 +854,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
style_small.leading = 10
story = [
- FontFallbackParagraph(self.verbose_name, style_h1),
+ PlainTextParagraph(self.verbose_name, style_h1),
Spacer(0, 3 * mm),
- FontFallbackParagraph(
- "
".join(escape(f) for f in self.describe_filters(form_data)),
+ PlainTextParagraph(
+ "\n".join(escape(f) for f in self.describe_filters(form_data)),
style_small,
),
]
@@ -870,7 +870,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
if s:
story += [
Spacer(0, 3 * mm),
- FontFallbackParagraph(_("Orders") + c_head, style_h2),
+ PlainTextParagraph(_("Orders") + c_head, style_h2),
Spacer(0, 3 * mm),
*s
]
@@ -881,7 +881,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
if s:
story += [
Spacer(0, 8 * mm),
- FontFallbackParagraph(_("Payments") + c_head, style_h2),
+ PlainTextParagraph(_("Payments") + c_head, style_h2),
Spacer(0, 3 * mm),
*s
]
@@ -894,7 +894,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
Spacer(0, 8 * mm),
KeepTogether(
[
- FontFallbackParagraph(_("Open items") + c_head, style_h2),
+ PlainTextParagraph(_("Open items") + c_head, style_h2),
Spacer(0, 3 * mm),
*s
]
@@ -912,7 +912,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
Spacer(0, 8 * mm),
KeepTogether(
[
- FontFallbackParagraph(_("Gift cards") + c_head, style_h2),
+ PlainTextParagraph(_("Gift cards") + c_head, style_h2),
Spacer(0, 3 * mm),
*s,
]
diff --git a/src/pretix/plugins/reports/exporters.py b/src/pretix/plugins/reports/exporters.py
index 6957ab396..98241865e 100644
--- a/src/pretix/plugins/reports/exporters.py
+++ b/src/pretix/plugins/reports/exporters.py
@@ -70,7 +70,7 @@ from pretix.base.timeframes import (
)
from pretix.control.forms.filter import OverviewFilterForm
from pretix.helpers.reportlab import (
- FontFallbackParagraph, register_ttf_font_if_new,
+ PlainTextParagraph, register_ttf_font_if_new,
)
from pretix.presale.style import get_fonts
@@ -282,7 +282,7 @@ class OverviewReport(Report):
headlinestyle.fontSize = 15
headlinestyle.fontName = 'OpenSansBd'
story = [
- FontFallbackParagraph(_('Orders by product') + ' ' + (_('(excl. taxes)') if net else _('(incl. taxes)')), headlinestyle),
+ PlainTextParagraph(_('Orders by product') + ' ' + (_('(excl. taxes)') if net else _('(incl. taxes)')), headlinestyle),
Spacer(1, 5 * mm)
]
return story
@@ -292,7 +292,7 @@ class OverviewReport(Report):
if form_data.get('date_axis') and form_data.get('date_range'):
d_start, d_end = resolve_timeframe_to_dates_inclusive(now(), form_data['date_range'], self.timezone)
story += [
- FontFallbackParagraph(_('{axis} between {start} and {end}').format(
+ PlainTextParagraph(_('{axis} between {start} and {end}').format(
axis=dict(OverviewFilterForm(event=self.event).fields['date_axis'].choices)[form_data.get('date_axis')],
start=date_format(d_start, 'SHORT_DATE_FORMAT') if d_start else '–',
end=date_format(d_end, 'SHORT_DATE_FORMAT') if d_end else '–',
@@ -305,13 +305,13 @@ class OverviewReport(Report):
subevent = self.event.subevents.get(pk=self.form_data.get('subevent'))
except SubEvent.DoesNotExist:
subevent = self.form_data.get('subevent')
- story.append(FontFallbackParagraph(pgettext('subevent', 'Date: {}').format(subevent), self.get_style()))
+ story.append(PlainTextParagraph(pgettext('subevent', 'Date: {}').format(subevent), self.get_style()))
story.append(Spacer(1, 5 * mm))
if form_data.get('subevent_date_range'):
d_start, d_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), form_data['subevent_date_range'], self.timezone)
story += [
- FontFallbackParagraph(_('{axis} between {start} and {end}').format(
+ PlainTextParagraph(_('{axis} between {start} and {end}').format(
axis=_('Event date'),
start=date_format(d_start, 'SHORT_DATE_FORMAT') if d_start else '–',
end=date_format(d_end - timedelta(hours=1), 'SHORT_DATE_FORMAT') if d_end else '–',
@@ -384,13 +384,13 @@ class OverviewReport(Report):
tdata = [
[
_('Product'),
- FontFallbackParagraph(_('Canceled'), tstyle_th),
+ PlainTextParagraph(_('Canceled'), tstyle_th),
'',
- FontFallbackParagraph(_('Expired'), tstyle_th),
+ PlainTextParagraph(_('Expired'), tstyle_th),
'',
- FontFallbackParagraph(_('Approval pending'), tstyle_th),
+ PlainTextParagraph(_('Approval pending'), tstyle_th),
'',
- FontFallbackParagraph(_('Purchased'), tstyle_th),
+ PlainTextParagraph(_('Purchased'), tstyle_th),
'', '', '', '', ''
],
[
@@ -421,14 +421,14 @@ class OverviewReport(Report):
for tup in items_by_category:
if tup[0]:
tdata.append([
- FontFallbackParagraph(str(tup[0]), tstyle_bold)
+ PlainTextParagraph(str(tup[0]), tstyle_bold)
])
for l, s in states:
tdata[-1].append(str(tup[0].num[l][0]))
tdata[-1].append(floatformat(tup[0].num[l][2 if net else 1], places))
for item in tup[1]:
tdata.append([
- FontFallbackParagraph(str(item), tstyle)
+ PlainTextParagraph(str(item), tstyle)
])
for l, s in states:
tdata[-1].append(str(item.num[l][0]))
@@ -436,7 +436,7 @@ class OverviewReport(Report):
if item.has_variations:
for var in item.all_variations:
tdata.append([
- FontFallbackParagraph(" " + str(var), tstyle)
+ PlainTextParagraph(" " + str(var), tstyle)
])
for l, s in states:
tdata[-1].append(str(var.num[l][0]))
@@ -568,7 +568,7 @@ class OrderTaxListReportPDF(Report):
tstyledata.append(('SPAN', (5 + 2 * i, 0), (6 + 2 * i, 0)))
story = [
- FontFallbackParagraph(_('Orders by tax rate ({currency})').format(currency=self.event.currency), headlinestyle),
+ PlainTextParagraph(_('Orders by tax rate ({currency})').format(currency=self.event.currency), headlinestyle),
Spacer(1, 5 * mm)
]
tdata = [