diff --git a/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf b/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf new file mode 100644 index 0000000000..a81d104ae6 --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-cropbox/bg.pdf @@ -0,0 +1,99 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/PageMode /UseNone +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/Count 1 +/Kids [ 3 0 R ] +/Type /Pages +>> +endobj +3 0 obj +<< +/Contents 4 0 R +/MediaBox [ 0 0 595.2756 841.8898 ] +/Parent 2 0 R +/Resources << +/Font 5 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/CropBox [ 10 10 307.84 220 ] +>> +endobj +4 0 obj +<< +/Length 117 +>> +stream +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q + +endstream +endobj +5 0 obj +<< +/F1 6 0 R +>> +endobj +6 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +7 0 obj +<< +/Author (anonymous) +/CreationDate (D\07220260917173038\05302\04700\047) +/Creator (anonymous) +/Keywords () +/ModDate (D\07220260917173038\05302\04700\047) +/Producer (ReportLab PDF Library \055 \050opensource\051) +/Subject (unspecified) +/Title (untitled) +/Trapped /False +>> +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000083 00000 n +0000000142 00000 n +0000000371 00000 n +0000000539 00000 n +0000000570 00000 n +0000000677 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +/Info 7 0 R +/ID [ ] +>> +startxref +966 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf b/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf new file mode 100644 index 0000000000..e0f7a11e4f --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-cropbox/expected.pdf @@ -0,0 +1,213 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 6 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +/F1-0 8 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +9 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 13 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +/F1-0 8 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000361 00000 n +0000000393 00000 n +0000000436 00000 n +0000000543 00000 n +0000000650 00000 n +0000000871 00000 n +0000001029 00000 n +0000001224 00000 n +0000001258 00000 n +0000001303 00000 n +0000001411 00000 n +0000001633 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +1791 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf b/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf new file mode 100644 index 0000000000..85ac42c236 --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-mediabox-offset/bg.pdf @@ -0,0 +1,98 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/PageMode /UseNone +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/Count 1 +/Kids [ 3 0 R ] +/Type /Pages +>> +endobj +3 0 obj +<< +/Contents 4 0 R +/MediaBox [ 10 10 307.84 220 ] +/Parent 2 0 R +/Resources << +/Font 5 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +>> +endobj +4 0 obj +<< +/Length 117 +>> +stream +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q + +endstream +endobj +5 0 obj +<< +/F1 6 0 R +>> +endobj +6 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +7 0 obj +<< +/Author (anonymous) +/CreationDate (D\07220260917173038\05302\04700\047) +/Creator (anonymous) +/Keywords () +/ModDate (D\07220260917173038\05302\04700\047) +/Producer (ReportLab PDF Library \055 \050opensource\051) +/Subject (unspecified) +/Title (untitled) +/Trapped /False +>> +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000083 00000 n +0000000142 00000 n +0000000336 00000 n +0000000504 00000 n +0000000535 00000 n +0000000642 00000 n +trailer +<< +/Size 8 +/Root 1 0 R +/Info 7 0 R +/ID [ ] +>> +startxref +931 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf b/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf new file mode 100644 index 0000000000..e0f7a11e4f --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-mediabox-offset/expected.pdf @@ -0,0 +1,213 @@ +%PDF-1.3 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 6 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +/F1-0 8 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +9 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 297.84 210 ] +/Resources << +/Font 13 0 R +/ProcSet [ /ImageB /ImageC /ImageI /PDF /Text ] +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +/F1-0 8 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 170 +>> +stream +q +1 0.0 0.0 1 -10 -10 cm +10 10 297.84 210 re +W +n +q +1 0.0 0.0 1 10 10 cm +1 0 0 1 0 0 cm +BT +/F1-0 12 Tf +14.4 TL +ET +1 0 0 rg +n +56.69291 56.69291 141.7323 28.34646 re +B* +Q +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000361 00000 n +0000000393 00000 n +0000000436 00000 n +0000000543 00000 n +0000000650 00000 n +0000000871 00000 n +0000001029 00000 n +0000001224 00000 n +0000001258 00000 n +0000001303 00000 n +0000001411 00000 n +0000001633 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +1791 +%%EOF diff --git a/src/tests/plugins/badges/assets/bg-rotated/bg.pdf b/src/tests/plugins/badges/assets/bg-rotated/bg.pdf new file mode 100644 index 0000000000..6be972deaf Binary files /dev/null and b/src/tests/plugins/badges/assets/bg-rotated/bg.pdf differ diff --git a/src/tests/plugins/badges/assets/bg-rotated/expected.pdf b/src/tests/plugins/badges/assets/bg-rotated/expected.pdf new file mode 100644 index 0000000000..0e8ee99c9d --- /dev/null +++ b/src/tests/plugins/badges/assets/bg-rotated/expected.pdf @@ -0,0 +1,216 @@ +%PDF-1.7 +%âãÏÓ +1 0 obj +<< +/Producer (pypdf) +>> +endobj +2 0 obj +<< +/Type /Pages +/Count 2 +/Kids [ 4 0 R 11 0 R ] +>> +endobj +3 0 obj +<< +/Type /Catalog +/Pages 2 0 R +>> +endobj +4 0 obj +<< +/Contents 5 0 R +/MediaBox [ 0 0 210 297.84 ] +/Resources << +/Font 6 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +/ExtGState << +/GS0 8 0 R +>> +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +5 0 obj +[ 9 0 R 10 0 R ] +endobj +6 0 obj +<< +/F1 7 0 R +>> +endobj +7 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +8 0 obj +<< +/Type /ExtGState +/OP false +/op false +/OPM 1 +>> +endobj +9 0 obj +<< +/Length 287 +>> +stream +q +0.00000000000000006123234 -1 1 0.00000000000000006123234 0.0 297.84 cm +0.0 0.0 297.84 210 re +W +n +/GS0 gs +0.925811 0.881331 0.538643 rg +0 0.23622 297.638 209.764 re +f* +0.476631 0.756542 0.260899 rg +0 0.23622 297.638 209.764 re +292.638 205 m +5 205 l +5 5.23622 l +292.638 5.23622 l +h +f* +Q + +endstream +endobj +10 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +11 0 obj +<< +/Contents 12 0 R +/MediaBox [ 0 0 210 297.84 ] +/Resources << +/Font 13 0 R +/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +/ExtGState << +/GS0 8 0 R +>> +>> +/Rotate 0 +/Trans << +>> +/Type /Page +/Parent 2 0 R +>> +endobj +12 0 obj +[ 15 0 R 16 0 R ] +endobj +13 0 obj +<< +/F1 14 0 R +>> +endobj +14 0 obj +<< +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding +/Name /F1 +/Subtype /Type1 +/Type /Font +>> +endobj +15 0 obj +<< +/Length 287 +>> +stream +q +0.00000000000000006123234 -1 1 0.00000000000000006123234 0.0 297.84 cm +0.0 0.0 297.84 210 re +W +n +/GS0 gs +0.925811 0.881331 0.538643 rg +0 0.23622 297.638 209.764 re +f* +0.476631 0.756542 0.260899 rg +0 0.23622 297.638 209.764 re +292.638 205 m +5 205 l +5 5.23622 l +292.638 5.23622 l +h +f* +Q + +endstream +endobj +16 0 obj +<< +/Length 106 +>> +stream +q +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 37.10551 140.9669 cm +q +1 0 0 1 0 5.669531 cm +Q +Q + + +Q + +endstream +endobj +xref +0 17 +0000000000 65535 f +0000000015 00000 n +0000000054 00000 n +0000000120 00000 n +0000000169 00000 n +0000000389 00000 n +0000000421 00000 n +0000000452 00000 n +0000000559 00000 n +0000000624 00000 n +0000000962 00000 n +0000001120 00000 n +0000001343 00000 n +0000001377 00000 n +0000001410 00000 n +0000001518 00000 n +0000001857 00000 n +trailer +<< +/Size 17 +/Root 3 0 R +/Info 1 0 R +>> +startxref +2015 +%%EOF diff --git a/src/tests/plugins/badges/test_pdf.py b/src/tests/plugins/badges/test_pdf.py index 8dcdc85544..49935c53bc 100644 --- a/src/tests/plugins/badges/test_pdf.py +++ b/src/tests/plugins/badges/test_pdf.py @@ -32,13 +32,18 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under the License. +import tempfile from datetime import timedelta from decimal import Decimal from io import BytesIO +from pathlib import Path +import pypdfium2 import pytest +from django.core.files import File from django.utils.timezone import now from django_scopes import scope +from PIL import ImageChops from pypdf import PdfReader from pretix.base.models import ( @@ -118,3 +123,49 @@ def test_generate_pdf_multi(env): assert ftype == 'application/pdf' pdf = PdfReader(BytesIO(buf)) assert len(pdf.pages) == 1 + + +def test_asset(name): + return Path(__file__).parent / "assets" / name + + +def compare_pdfs(inp_a: Path | bytes, inp_b: Path | bytes): + pdf_a = pypdfium2.PdfDocument(inp_a) + pdf_b = pypdfium2.PdfDocument(inp_b) + + assert len(pdf_a) == len(pdf_b) + + for i, (expected_page, output_page) in enumerate(zip(pdf_a, pdf_b)): + expected_render = expected_page.render() + output_render = output_page.render() + assert expected_render.height == output_render.height + assert expected_render.width == output_render.width + + diff = ImageChops.difference(expected_render.to_pil(), output_render.to_pil()) + if diff.getbbox(): + with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as f: + diff.save(f) + assert not diff.getbbox(), f"Page {i} differs. Diff was written to {f.name}" + + +@pytest.mark.django_db +@pytest.mark.parametrize("case", [ + "bg-rotated", + "bg-mediabox-offset", + "bg-cropbox" +]) +def test_generate_pdf_weird_bgs(env, case): + event, order, shirt = env + asset_folder = test_asset(case) + with open(asset_folder / "bg.pdf", 'rb') as fi: + event.badge_layouts.create(name="Default", default=True, background=File(fi, name="test.pdf")) + e = BadgeExporter(event, organizer=event.organizer) + fname, ftype, buf = e.render({ + 'items': [shirt.pk], + 'rendering': 'one', + 'include_pending': True + }) + assert ftype == 'application/pdf' + assert buf + + compare_pdfs(buf, asset_folder / "expected.pdf")