Files
Tracker/Code/Tools/Samples/generators/pdf_filing_receipt.py
T
2026-02-21 21:55:42 +00:00

139 lines
3.9 KiB
Python

"""Generate PDF: IPD Filing Receipt (native text PDF, bilingual)."""
from pathlib import Path
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
from generators.cjk_font import register_cjk_font
def _set_font(c, bold=False, size=10):
"""Set font with CJK support."""
cjk = register_cjk_font()
if cjk != "Helvetica":
c.setFont(cjk, size)
else:
c.setFont("Helvetica-Bold" if bold else "Helvetica", size)
def _has_cjk(text):
"""Check if text contains CJK characters."""
return any(ord(ch) > 0x2E80 for ch in text)
def generate(
output_path: Path,
ipd: dict,
tm_number: str,
tm_text: str,
applicant: str,
applicant_address: str,
agent: str,
agent_address: str,
filing_date: str,
response_deadline: str,
nice_class: str,
class_description: str,
):
"""Generate an IPD filing receipt PDF."""
cjk = register_cjk_font()
c = canvas.Canvas(str(output_path), pagesize=A4)
w, h = A4
def draw_text(x, y_pos, text, size=10, bold=False, centered=False):
"""Draw text, auto-switching to CJK font if needed."""
if _has_cjk(text) and cjk != "Helvetica":
c.setFont(cjk, size)
else:
c.setFont("Helvetica-Bold" if bold else "Helvetica", size)
if centered:
c.drawCentredString(x, y_pos, text)
else:
c.drawString(x, y_pos, text)
# Header
draw_text(w / 2, h - 50, ipd["name"], 12, bold=True, centered=True)
draw_text(w / 2, h - 66, ipd["chinese_name"], 10, centered=True)
draw_text(
w / 2,
h - 82,
"The Government of the Hong Kong Special Administrative Region",
10,
centered=True,
)
# Divider
c.setStrokeColor(HexColor("#333333"))
c.setLineWidth(1)
c.line(50, h - 95, w - 50, h - 95)
# Title
draw_text(
w / 2,
h - 120,
"E-Filing Receipt / Acknowledgment",
14,
bold=True,
centered=True,
)
# Receipt details
y = h - 160
fields = [
("Receipt No.:", f"EF-{tm_number[-6:]}"),
("Application No. / 申請編號:", tm_number),
("Trade Mark Text / 商標文字:", tm_text),
("Mark Type / 商標種類:", "Ordinary"),
("Class No. / 類別編號:", nice_class),
("Specification / 貨品/服務說明:", class_description),
("", ""),
("Applicant / 申請人:", applicant),
("Address / 地址:", applicant_address),
("", ""),
("Agent / 代理人:", agent),
("Agent Address / 代理人地址:", agent_address),
("", ""),
("Date of Filing / 提交日期:", filing_date),
("Date of Receipt / 確認日期:", filing_date),
]
for label, value in fields:
if not label and not value:
y -= 10
continue
draw_text(50, y, label, 10, bold=True)
# Wrap long values
if len(value) > 60:
draw_text(250, y, value[:60], 10)
y -= 16
draw_text(250, y, value[60:120], 10)
else:
draw_text(250, y, value, 10)
y -= 18
# Response deadline (highlighted)
y -= 15
c.setStrokeColor(HexColor("#cc0000"))
c.setLineWidth(0.5)
c.rect(40, y - 10, w - 80, 40, stroke=1, fill=0)
c.setFillColor(HexColor("#cc0000"))
draw_text(50, y + 12, "IMPORTANT / 重要通知:", 11, bold=True)
c.setFillColor(HexColor("#000000"))
draw_text(50, y - 4, f"Response deadline / 回覆限期: {response_deadline}", 10)
# Footer
y -= 50
c.setFillColor(HexColor("#666666"))
draw_text(
w / 2,
y,
"This is a computer-generated receipt. No signature is required.",
8,
centered=True,
)
draw_text(w / 2, y - 14, "此為電腦自動產生之收據,毋須簽署。", 8, centered=True)
c.save()