buildPdf($jpeg, $title, $width, $height); } private function buildPdf(string $jpeg, string $title, int $imgW, int $imgH): string { $pageW = 595.28; $pageH = 841.89; $margin = 48; $maxQr = min($pageW - ($margin * 2), 320); $scale = min($maxQr / max(1, $imgW), $maxQr / max(1, $imgH)); $drawW = $imgW * $scale; $drawH = $imgH * $scale; $x = ($pageW - $drawW) / 2; $y = 120; $safeTitle = $this->pdfEscape(substr($title, 0, 80)); $objects = []; $objects[] = "1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n"; $objects[] = "2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj\n"; $objects[] = sprintf( "3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 %.2F %.2F] /Resources << /Font << /F1 4 0 R >> /XObject << /Im1 5 0 R >> >> /Contents 6 0 R >> endobj\n", $pageW, $pageH, ); $objects[] = "4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold >> endobj\n"; $objects[] = sprintf( "5 0 obj << /Type /XObject /Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length %d >> stream\n%s\nendstream\nendobj\n", $imgW, $imgH, strlen($jpeg), $jpeg, ); $content = "BT /F1 16 Tf 48 " . ($pageH - 72) . " Td ({$safeTitle}) Tj ET\n"; $content .= sprintf("q %.4F 0 0 %.4F %.2F %.2F cm /Im1 Do Q\n", $drawW, $drawH, $x, $pageH - $y - $drawH); $content .= "BT /F1 10 Tf 48 48 Td (Generated by Ladill QR Codes) Tj ET\n"; $objects[] = sprintf("6 0 obj << /Length %d >> stream\n%s\nendstream\nendobj\n", strlen($content), $content); $pdf = "%PDF-1.4\n"; $offsets = [0]; foreach ($objects as $object) { $offsets[] = strlen($pdf); $pdf .= $object; } $xrefPos = strlen($pdf); $pdf .= "xref\n0 " . count($offsets) . "\n"; $pdf .= "0000000000 65535 f \n"; for ($i = 1; $i < count($offsets); $i++) { $pdf .= sprintf("%010d 00000 n \n", $offsets[$i]); } $pdf .= "trailer << /Size " . count($offsets) . " /Root 1 0 R >>\n"; $pdf .= "startxref\n{$xrefPos}\n%%EOF"; return $pdf; } private function pdfEscape(string $text): string { return str_replace(['\\', '(', ')'], ['\\\\', '\\(', '\\)'], $text); } }