Add pdf-invoice module: one invoice in OpenPDF 3.0.5, iText Core 9.8.0 and Flying Saucer 10.7.0, Devanagari shaping checked by rendering, streamed vs buffered download, subset sizes and timings
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b6Kg9RWSTJzyz6KP9X
@@ -0,0 +1,20 @@
|
||||
# licences as declared in the POMs Maven downloaded (~/.m2) and in the pdfCalligraph POM on iText's own repository, fetched 2026-10-30
|
||||
openpdf 3.0.5 (declared in openpdf-parent): GNU Lesser General Public License (LGPL), Version 2.1;Mozilla Public License Version 2.0;
|
||||
itext kernel/layout 9.8.0 (root pom): GNU Affero General Public License v3;
|
||||
flying-saucer-pdf 10.7.0 (flying-saucer-parent): GNU Lesser General Public License (LGPL), version 2.1 or later;
|
||||
typography (pdfCalligraph) 5.1.1: Proprietary License;
|
||||
|
||||
# sentences from https://itextpdf.com/how-buy/agpl-license (verbatim, page text with tags stripped)
|
||||
- With the onset of e-invoicing legislation coming into effect across Europe, there is renewed interest in the ZUGFeRD/Factur-X hybrid invoice standard. This article examines how the standard has evolved, and how you can use the dual-licensed iText Core library to easily create ZUGFeRD-compatible files to comply with EN 16931 requirements.
|
||||
- iText 5 and all subsequent versions of iText are dual-licensed, and available under open source (AGPLv3) or commercial license agreements. Since iText is
|
||||
- If you cannot comply with the AGPLv3 terms, we offer commercial licensing options. Purchasing a commercial license will release you from the AGPLv3 copyleft restrictions, allowing you to keep your applications closed-source to your users.
|
||||
- You may not deploy it on a network without disclosing the full source code of your own applications under the AGPL license. You must distribute all source code, including your own product and web-based applications.
|
||||
- It’s a legal violation to use iText Core/Community and our open source add-ons in a non-AGPL environment.
|
||||
- When using iText Core/Community under AGPL, you must prominently mention iText and include the iText copyright and AGPL license in output file metadata, and also retain the producer line in every PDF that is created or manipulated using iText.
|
||||
|
||||
# versions: latest GA per maven-metadata.xml
|
||||
com/github/librepdf/openpdf latest 3.0.5
|
||||
com/itextpdf/kernel latest 9.8.0
|
||||
org/xhtmlrenderer/flying-saucer-pdf latest 10.7.0
|
||||
org/xhtmlrenderer/flying-saucer-pdf-openpdf latest 9.4.0
|
||||
org/apache/pdfbox/pdfbox latest 3.0.8
|
||||
@@ -0,0 +1,125 @@
|
||||
# PDFBox 3.0.8 text extraction of each engine's invoice, written by PdfContentTest
|
||||
|
||||
=== flyingsaucer (20012 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
From / विक्रेता Bill to / ग्राहक
|
||||
Ankur Book House, Mumbai श्रीमती क्षमा कुलकर्णी
|
||||
12 Dadar Market Road, Mumbai 400014 पुणे, महाराष्ट्र 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
Item / तपशील Qty Rate Amount / रक्कम
|
||||
ज्ञानेश्वरी – संपूर्ण ग्रंथ (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
प्रोग्रामिंग की कला (हिन्दी) 1 ₹ 899.00 ₹ 899.00
|
||||
विद्वान कर्मचारी मार्गदर्शिका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
Subtotal / उपबेरीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
कृपया धन्यवाद — द्वारा: अंकुर बुक हाऊस. Payment due in 15 days.
|
||||
|
||||
=== flyingsaucer-shaped (21537 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
From / ववकेता Bill to / गाहक
|
||||
Ankur Book House, Mumbai शीमती कमा कुलकणर
|
||||
12 Dadar Market Road, Mumbai 400014 पणु,े महाराष् 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
Item / तपशील Qty Rate Amount / रककम
|
||||
जानशेरी – सपंणू र गथं (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
पोगाममरग की कला (हहनदी) 1 ₹ 899.00 ₹ 899.00
|
||||
ववदान कमचर ारी मागदर रशरका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
Subtotal / उपबरेीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
कृपया धनयवाद — दारा: अकुंर बकु हाऊस. Payment due in 15 days.
|
||||
|
||||
=== itext (23344 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
From / विक्रेता Bill to / ग्राहक
|
||||
Ankur Book House, Mumbai श्रीमती क्षमा कुलकर्णी
|
||||
12 Dadar Market Road, Mumbai 400014 पुणे, महाराष्ट्र 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
Item / तपशील Qty Rate Amount / रक्कम
|
||||
ज्ञानेश्वरी – संपूर्ण ग्रंथ (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
प्रोग्रामिंग की कला (हिन्दी) 1 ₹ 899.00 ₹ 899.00
|
||||
विद्वान कर्मचारी मार्गदर्शिका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
Subtotal / उपबेरीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
कृपया धन्यवाद — द्वारा: अंकुर बुक हाऊस. Payment due in 15 days.
|
||||
|
||||
=== openpdf (20039 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
|
||||
From / विक्रेता Bill to / ग्राहक
|
||||
Ankur Book House, Mumbai श्रीमती क्षमा कुलकर्णी
|
||||
12 Dadar Market Road, Mumbai 400014 पुणे, महाराष्ट्र 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
|
||||
Item / तपशील Qty Rate Amount / रक्कम
|
||||
ज्ञानेश्वरी – संपूर्ण ग्रंथ (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
प्रोग्रामिंग की कला (हिन्दी) 1 ₹ 899.00 ₹ 899.00
|
||||
विद्वान कर्मचारी मार्गदर्शिका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
|
||||
Subtotal / उपबेरीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
|
||||
कृपया धन्यवाद — द्वारा: अंकुर बुक हाऊस. Payment due in 15 days.
|
||||
|
||||
=== openpdf-jdk (21553 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
|
||||
From / ववकेता Bill to / गाहक
|
||||
Ankur Book House, Mumbai शीमती कमा कुलकणर
|
||||
12 Dadar Market Road, Mumbai 400014 पुणे, महाराष् 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
|
||||
Item / तपशील Qty Rate Amount / रककम
|
||||
जानशेरी – संपूणर गंथ (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
पोगाममरग की कला (हहनदी) 1 ₹ 899.00 ₹ 899.00
|
||||
ववदान कमरचारी मागदर रशरका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
|
||||
Subtotal / उपबरेीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
|
||||
कृपया धनयवाद — दारा: अंकुर बकु हाऊस. Payment due in 15 days.
|
||||
|
||||
=== openpdf-jdk-actualtext (22285 bytes) ===
|
||||
Tax Invoice / कर चलन
|
||||
Invoice INV-2026-0042 | 2026-10-30
|
||||
|
||||
From / विक्रेता Bill to / ग्राहक
|
||||
Ankur Book House, Mumbai श्रीमती क्षमा कुलकर्णी
|
||||
12 Dadar Market Road, Mumbai 400014 पुणे, महाराष्ट्र 411004
|
||||
GSTIN 27AAAAA0000A1Z5 GSTIN 27BBBBB1111B1Z6
|
||||
|
||||
Item / तपशील Qty Rate Amount / रक्कम
|
||||
ज्ञानेश्वरी – संपूर्ण ग्रंथ (मराठी) 2 ₹ 450.00 ₹ 900.00
|
||||
प्रोग्रामिंग की कला (हिन्दी) 1 ₹ 899.00 ₹ 899.00
|
||||
विद्वान कर्मचारी मार्गदर्शिका 3 ₹ 125.50 ₹ 376.50
|
||||
Spring Boot 4 Handbook 1 ₹ 1,299.00 ₹ 1,299.00
|
||||
|
||||
Subtotal / उपबेरीज ₹ 3,474.50
|
||||
CGST 9% + SGST 9% / कर ₹ 625.41
|
||||
Total / एकूण ₹ 4,099.91
|
||||
|
||||
कृपया धन्यवाद — द्वारा: अंकुर बुक हाऊस. Payment due in 15 days.
|
||||
|
||||
fonts flyingsaucer [LXEQIC+NotoSansDevanagari-Bold embedded=true, OUOZGZ+NotoSansDevanagari-Regular embedded=true]
|
||||
|
||||
fonts flyingsaucer-shaped [GJBPWA+NotoSansDevanagari-Bold embedded=true, FYEFNQ+NotoSansDevanagari-Regular embedded=true]
|
||||
|
||||
fonts itext [YCXTVQ+NotoSansDevanagari-Bold embedded=true, PXNQYY+NotoSansDevanagari-Regular embedded=true]
|
||||
|
||||
fonts openpdf [FFJNLO+NotoSansDevanagari-Bold embedded=true, CRMHHV+NotoSansDevanagari-Regular embedded=true]
|
||||
|
||||
fonts openpdf-jdk-actualtext [GEKVVR+NotoSansDevanagari-Bold embedded=true, PPYLBT+NotoSansDevanagari-Regular embedded=true]
|
||||
@@ -0,0 +1,47 @@
|
||||
# HTTP: status and headers per engine (curl -D -), then streaming vs buffered, then a failure after rendering
|
||||
# openjdk version "25.0.5" 2026-10-20 LTS | 2 vCPU | 8027 MB RAM
|
||||
--- GET /invoices/openpdf.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/itext.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/flyingsaucer.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/openpdf-jdk.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/openpdf-jdk-actualtext.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/flyingsaucer-shaped.pdf
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: attachment; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
Content-Type: application/pdf
|
||||
Transfer-Encoding: chunked
|
||||
--- GET /invoices/openpdf.pdf?mode=buffered
|
||||
HTTP/1.1 200
|
||||
Content-Length: 20039
|
||||
--- GET /invoices/openpdf.pdf?disposition=inline
|
||||
HTTP/1.1 200
|
||||
Content-Disposition: inline; filename="__-INV-2026-0042.pdf"; filename*=UTF-8''%E0%A4%AC%E0%A4%BF%E0%A4%B2-INV-2026-0042.pdf
|
||||
--- GET /invoices/nope.pdf
|
||||
HTTP/1.1 404
|
||||
--- GET /invoices/openpdf.pdf?failAtEnd=true (streamed: headers are already gone when the failure happens)
|
||||
HTTP/1.1 200
|
||||
Transfer-Encoding: chunked
|
||||
curl exit=18 bytes_received=20039
|
||||
--- GET /invoices/openpdf.pdf?failAtEnd=true&mode=buffered (rendered into memory first)
|
||||
HTTP/1.1 500
|
||||
curl exit=0 bytes_received=116
|
||||
@@ -0,0 +1,43 @@
|
||||
# pdffonts per engine (poppler): name, type, embedded, subset
|
||||
--- openpdf (20039 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
QVECCU+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 1 0
|
||||
LWDRDP+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 2 0
|
||||
--- itext (23344 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
BYDHEU+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 6 0
|
||||
EUBWBF+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 7 0
|
||||
--- flyingsaucer (20011 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
AKIOED+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 2 0
|
||||
WSTLFR+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 3 0
|
||||
--- openpdf-jdk (21553 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
SJCTQQ+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 1 0
|
||||
SDAHWP+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 2 0
|
||||
--- openpdf-jdk-actualtext (22285 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
VNADNX+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 1 0
|
||||
EAQUGS+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 2 0
|
||||
--- flyingsaucer-shaped (21536 bytes)
|
||||
name type encoding emb sub uni object ID
|
||||
------------------------------------ ----------------- ---------------- --- --- --- ---------
|
||||
RTHNRU+NotoSansDevanagari-Bold CID TrueType Identity-H yes yes yes 2 0
|
||||
STZJGA+NotoSansDevanagari-Regular CID TrueType Identity-H yes yes yes 3 0
|
||||
|
||||
# Producer/Creator lines the libraries write into the PDF (pdfinfo)
|
||||
--- openpdf
|
||||
Title: Invoice INV-2026-0042
|
||||
Producer: OpenPDF 3.0.5
|
||||
--- itext
|
||||
Title: Invoice INV-2026-0042
|
||||
Producer: iText® Core 9.8.0 (AGPL version) ©2000-2026 Apryse Group NV
|
||||
--- flyingsaucer
|
||||
Title: Invoice INV-2026-0042
|
||||
Creator: Flying Saucer 10.7.0 with OpenPDF 3.0.5
|
||||
Producer: Flying Saucer 10.7.0 with OpenPDF 3.0.5
|
||||
@@ -0,0 +1,9 @@
|
||||
# glyph codes written into page 1 content streams for the probe invoice (Identity-H, 2 bytes each)
|
||||
# code points drawn, spaces excluded: 364
|
||||
# the engines also draw the spaces as glyphs, so read the numbers against each other, not against this one
|
||||
openpdf glyph codes: 427
|
||||
itext glyph codes: 423
|
||||
flyingsaucer glyph codes: 421
|
||||
openpdf-jdk glyph codes: 387
|
||||
openpdf-jdk-actualtext glyph codes: 387
|
||||
flyingsaucer-shaped glyph codes: 381
|
||||
@@ -0,0 +1,4 @@
|
||||
# LayoutProcessor.enable() in the same JVM, then two other OpenPDF writers, then disable()
|
||||
openpdf: RuntimeException: Font creation failed for NotoSansDevanagari-Regular.ttf. | root cause IOException: NotoSansDevanagari-Regular.ttf not found as file or resource.
|
||||
openpdf-jdk: IllegalStateException: LayoutProcessor is enabled. Don't use the deprecated LayoutProcessor! | root cause IllegalStateException: LayoutProcessor is enabled. Don't use the deprecated LayoutProcessor!
|
||||
after LayoutProcessor.disable(): openpdf-jdk rendered normally
|
||||
@@ -0,0 +1,16 @@
|
||||
# in-process timing, openjdk version "25.0.5" 2026-10-20 LTS | 2 vCPU | 8027 MB RAM
|
||||
# indicative: shared sandbox, one JVM, one run per line
|
||||
# n=500 invoices per engine after 100 warm-up, one JVM, engines run one after another
|
||||
# OpenJDK 64-Bit Server VM 25.0.5 | 2 vCPU
|
||||
engine first_ms mean_ms p95_ms total_s pdf_bytes
|
||||
openpdf 377.0 7.93 18.89 3.96 20034
|
||||
itext 330.9 15.88 36.38 7.94 23338
|
||||
flyingsaucer 1163.4 28.05 57.66 14.02 20008
|
||||
openpdf-jdk-actualtext 423.5 42.89 107.47 21.45 22281
|
||||
flyingsaucer-shaped 107.5 49.99 93.45 24.99 21537
|
||||
# subset=false (whole font embedded), same invoice, one render each
|
||||
openpdf subset=20025 bytes, whole font=186300 bytes
|
||||
itext subset=23330 bytes, whole font=200149 bytes
|
||||
flyingsaucer subset=19996 bytes, whole font=186308 bytes
|
||||
openpdf-jdk-actualtext subset=22268 bytes, whole font=187399 bytes
|
||||
flyingsaucer-shaped subset=21525 bytes, whole font=186691 bytes
|
||||
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 98 KiB |