Add support for badge PDFs also

* Add a greyscale filter to text for more accurate preview
* Always default to SVG preview as it's the most accurate (cairo
  doesn't do a great job of handling custom fonts when it converts to
  png/pdf)
* Always use roboto font.
This commit is contained in:
James Polley 2017-12-26 23:55:09 +11:00
parent fcbacc82e6
commit f675580d6b
3 changed files with 24 additions and 14 deletions

View file

@ -18,11 +18,15 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
xmlns:serif="http://www.serif.com/"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<filter id="grayscale">
<feColorMatrix type="saturate" values="0"/>
</filter>
<g transform="matrix(1.40952,0,0,0.70946,0,0)">
<rect x="0" y="0" width="1240.16" height="1748.03"
style="fill:none;stroke:black;stroke-width:12.5px;" />
style="fill:white;stroke:black;stroke-width:12.5px;" />
</g>
<g transform="matrix(0.999321,0,0,0.999446,0,-507.874)">
@ -1042,18 +1046,18 @@ style="font-family:'Roboto-Regular', 'Roboto';font-size:88.353px;">
<g transform="matrix(0.607846,0,0,0.607922,138.923,372.07)">
<text x="0px" y="0px"
style="font-family:'Roboto-Regular', 'Roboto';font-size:144.577px;">
style="font-family:'Roboto-Regular', 'Roboto';font-size:144.577px;" filter="url(#grayscale)">
{{ user.attendee.attendeeprofilebase.attendeeprofile.name }}</text>
</g>
<g transform="matrix(0.607846,0,0,0.607922,138.923,449.05)">
<text x="0px" y="0px"
style="font-family:'Roboto-Regular', 'Roboto';font-size:96.385px;">
style="font-family:'Roboto-Regular', 'Roboto';font-size:96.385px;" filter="url(grayscale)">
{{ user.attendee.attendeeprofilebase.attendeeprofile.company }}</text>
</g>
<g transform="matrix(0.607846,0,0,0.607922,140.5,504.582)">
<g transform="matrix(0.607846,0,0,0.607922,140.5,504.582)" filter="url(#grayscale)">
<text x="0px" y="0px"
style="font-family:'Roboto-Regular', 'Roboto';font-size:60.24px;">
@ -1063,7 +1067,7 @@ style="font-family:'Roboto-Regular', 'Roboto';font-size:60.24px;">
<g transform="matrix(0.607846,0,0,0.607922,140.5,550.359)">
<text x="0px" y="0px"
style="font-family:'Roboto-Regular', 'Roboto';font-size:60.24px;">
style="font-family:'Roboto-Regular', 'Roboto';font-size:60.24px;" filter="url(#grayscale)">
{{ user.attendee.attendeeprofilebase.attendeeprofile.free_text_2 }}</text>
</g>
@ -1072,21 +1076,21 @@ style="font-family:'Roboto-Regular', 'Roboto';font-size:60.24px;">
<g id="text23417" transform="matrix(1,0,0,1,353.552,780.612)">
<text x="0px" y="0px"
style="font-family:'LucidaGrande-Bold', 'Lucida Grande', sans-serif;font-weight:600;font-size:72.288px;">
style="font-family:'Roboto-Bold', 'Roboto', sans-serif;font-weight:600;font-size:72.288px;">
{{ penguin_dinner_count }}</text>
</g>
<g id="text23421" transform="matrix(1,0,0,1,555.167,780.612)">
<text x="0px" y="0px"
style="font-family:'LucidaGrande-Bold', 'Lucida Grande', sans-serif;font-weight:600;font-size:72.288px;">
style="font-family:'Roboto-Bold', 'Roboto', sans-serif;font-weight:600;font-size:72.288px;">
{{ speakers_dinner_count }}</text>
</g>
<g id="text23425" transform="matrix(1,0,0,1,753.962,780.612)">
<text x="0px" y="0px"
style="font-family:'LucidaGrande-Bold', 'Lucida Grande', sans-serif;font-weight:600;font-size:72.288px;">
style="font-family:'Roboto-Bold', 'Roboto', sans-serif;font-weight:600;font-size:72.288px;">
{{ pdns_count }}</text>
</g>
@ -1379,7 +1383,7 @@ style="fill:white;fill-rule:nonzero;" />
<g id="text4601" transform="matrix(1,0,0,1,138.88,770.07)">
<text x="0px" y="0px"
style="font-family:'LucidaGrande-Bold', 'Lucida Grande', sans-serif;font-weight:600;font-size:40.16px;">
style="font-family:'Roboto-Bold', 'Roboto', sans-serif;font-weight:600;font-size:40.16px;">
{% if user.attendee.attendeeprofilebase.attendeeprofile.of_legal_age %}18+{% endif %}</text>
</g>
</g>

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View file

@ -27,9 +27,9 @@ from .views import (
public = [
url(r"^amend/([0-9]+)$", amend_registration, name="amend_registration"),
url(r"^mybadge$", user_badge, name="user_badge"),
url(r"^mybadge/(png|svg)", user_badge, name="user_badge"),
url(r"^mybadge\.(png|svg|pdf)", user_badge, name="user_badge"),
url(r"^badge/([0-9]+)$", badge, name="badge"),
url(r"^badge/([0-9]+).(png|svg)$", badge, name="badge"),
url(r"^badge/([0-9]+).(png|svg|pdf)$", badge, name="badge"),
url(r"^badger/([A-Za-z0-9]+)$", badger, name="badger"),
url(r"^badger/", badger, name="badger"),
url(r"^category/([0-9]+)$", product_category, name="product_category"),

View file

@ -38,7 +38,7 @@ from django.template import Context, Template, loader
from lxml import etree
from copy import deepcopy
from cairosvg import svg2png
from cairosvg import svg2pdf, svg2png
from registrasion.forms import BadgeForm, ticket_selection
from registrasion.contrib.badger import (
@ -1114,7 +1114,7 @@ def _get_badge_template_name():
return os.path.join(settings.PROJECT_ROOT, 'pinaxcon', 'templates',
settings.BADGER_DEFAULT_SVG)
@login_required
def user_badge(request, format="png"):
def user_badge(request, format="svg"):
'''Shows the logged-in user their badge'''
return render_badge(request.user, format)
@ -1131,7 +1131,9 @@ def badge(request, user_id, format="svg"):
def render_badge(user, format="svg"):
rendered = render_badge_svg(user)
if format == "png":
rendered = svg2png(bytestring=svg, dpi=72, scale=3)
rendered = svg2png(bytestring=rendered, dpi=72, scale=3)
elif format == "pdf":
rendered = svg2pdf(bytestring=rendered, dpi=72, scale=3)
response = HttpResponse(rendered)
@ -1141,6 +1143,10 @@ def render_badge(user, format="svg"):
elif format == "png":
response["Content-Type"] = "image/png"
response["Content-Disposition"] = 'inline; filename="badge.png"'
elif format == "pdf":
response["Content-Type"] = "application/pdf"
response["Content-Disposition"] = 'inline; filename="badge.pdf"'
return response
def render_badge_svg(user):