"""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()