This commit is contained in:
+47
-18
@@ -1220,27 +1220,56 @@ function wrapPdfLines(lines, width=92){
|
||||
function buildPdfBytes(lines){
|
||||
const encoder=new TextEncoder();
|
||||
const title=String(lines[0]||"PIZZATEIG");
|
||||
const body=wrapPdfLines(lines.slice(1));
|
||||
const pageSize=46;
|
||||
const pages=[];
|
||||
for(let i=0;i<Math.max(1,Math.ceil(body.length/pageSize));i++) pages.push(body.slice(i*pageSize,(i+1)*pageSize));
|
||||
let body=wrapPdfLines(lines.slice(1),88);
|
||||
const maxRows=62;
|
||||
if(body.length>maxRows) body=[...body.slice(0,maxRows-1),"[... weitere Angaben gekürzt]"];
|
||||
|
||||
const units=body.reduce((sum,line)=>sum+(line ? 1 : .55),0)||1;
|
||||
const lineHeight=Math.max(8.5,Math.min(13,610/units));
|
||||
const bodySize=Math.max(6.8,Math.min(9.5,lineHeight-1.8));
|
||||
|
||||
let stream="q\n";
|
||||
// Dunkle Grundfläche und dezentes Terminal-Raster.
|
||||
stream+="0.027 0.031 0.043 rg 0 0 595 842 re f\n";
|
||||
stream+="0.055 0.082 0.114 RG 0.3 w\n";
|
||||
for(let x=19;x<595;x+=32) stream+=`${x} 0 m ${x} 842 l S\n`;
|
||||
for(let y=10;y<842;y+=32) stream+=`0 ${y} m 595 ${y} l S\n`;
|
||||
// Panel, Neon-Kanten und asymmetrische Akzentleisten.
|
||||
stream+="0.063 0.082 0.122 rg 28 58 539 704 re f\n";
|
||||
stream+="0 0.941 1 RG 0.9 w 28 58 539 704 re S\n";
|
||||
stream+="0 0.941 1 rg 28 786 539 3 re f\n";
|
||||
stream+="1 0.176 0.471 rg 28 776 128 5 re f\n";
|
||||
stream+="1 0.176 0.471 rg 552 58 15 15 re f\nQ\n";
|
||||
|
||||
// Kopfzeile im Stil der Anwendung.
|
||||
stream+=`BT\n/F2 22 Tf\n0 0.941 1 rg\n36 805 Td\n<${winAnsiHex("TEIG//TERMINAL")}> Tj\nET\n`;
|
||||
stream+=`BT\n/F1 7.5 Tf\n1 0.176 0.471 rg\n37 793 Td\n<${winAnsiHex("RECIPE EXPORT // OFFLINE GENERATED // SYSTEM READY")}> Tj\nET\n`;
|
||||
stream+=`BT\n/F2 14 Tf\n0.922 0.965 1 rg\n42 741 Td\n<${winAnsiHex(title)}> Tj\nET\n`;
|
||||
stream+="0 0.941 1 RG 0.7 w 42 729 m 553 729 l S\n";
|
||||
|
||||
let y=711;
|
||||
body.forEach(line=>{
|
||||
if(!line){ y-=lineHeight*.55; return; }
|
||||
const section=/^[A-ZÄÖÜ][A-ZÄÖÜ0-9 /()%-]{2,}$/.test(line.trim()) && line.trim().length<42;
|
||||
const isLink=/^https?:\/\//.test(line.trim());
|
||||
const font=section?"F2":"F1";
|
||||
const size=section?Math.min(10.5,bodySize+1):isLink?Math.max(6.5,bodySize-1):bodySize;
|
||||
const color=section?"1 0.176 0.471":isLink?"0 0.941 1":"0.886 0.925 0.961";
|
||||
if(section) stream+=`0 0.941 1 rg 42 ${y-1.5} 5 5 re f\n`;
|
||||
stream+=`BT\n/${font} ${size.toFixed(1)} Tf\n${color} rg\n${section?53:42} ${y.toFixed(1)} Td\n<${winAnsiHex(line.trimEnd())}> Tj\nET\n`;
|
||||
y-=lineHeight;
|
||||
});
|
||||
|
||||
stream+="0 0.941 1 RG 0.5 w 42 47 m 553 47 l S\n";
|
||||
stream+=`BT\n/F1 7 Tf\n0 0.941 1 rg\n42 35 Td\n<${winAnsiHex("TEIG//TERMINAL // LOCAL PDF // A4 // 1 OF 1")}> Tj\nET\n`;
|
||||
|
||||
const objects=[];
|
||||
objects[1]="<< /Type /Catalog /Pages 2 0 R >>";
|
||||
objects[3]="<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>";
|
||||
objects[4]="<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>";
|
||||
const pageRefs=[];
|
||||
|
||||
pages.forEach((pageLines,index)=>{
|
||||
const contentId=5+index*2, pageId=contentId+1;
|
||||
pageRefs.push(`${pageId} 0 R`);
|
||||
let stream=`BT\n/F2 16 Tf\n50 800 Td\n<${winAnsiHex(title)}> Tj\n/F1 10 Tf\n0 -26 Td\n14 TL\n`;
|
||||
pageLines.forEach(line=>{ stream+=`<${winAnsiHex(line)}> Tj\nT*\n`; });
|
||||
stream+=`ET\nBT\n/F1 8 Tf\n50 32 Td\n<${winAnsiHex(`TEIG//TERMINAL · Seite ${index+1} / ${pages.length}`)}> Tj\nET\n`;
|
||||
objects[contentId]=`<< /Length ${encoder.encode(stream).length} >>\nstream\n${stream}endstream`;
|
||||
objects[pageId]=`<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 3 0 R /F2 4 0 R >> >> /Contents ${contentId} 0 R >>`;
|
||||
});
|
||||
objects[2]=`<< /Type /Pages /Kids [${pageRefs.join(" ")}] /Count ${pages.length} >>`;
|
||||
objects[2]="<< /Type /Pages /Kids [6 0 R] /Count 1 >>";
|
||||
objects[3]="<< /Type /Font /Subtype /Type1 /BaseFont /Courier /Encoding /WinAnsiEncoding >>";
|
||||
objects[4]="<< /Type /Font /Subtype /Type1 /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding >>";
|
||||
objects[5]=`<< /Length ${encoder.encode(stream).length} >>\nstream\n${stream}endstream`;
|
||||
objects[6]="<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 3 0 R /F2 4 0 R >> >> /Contents 5 0 R >>";
|
||||
|
||||
const chunks=[encoder.encode("%PDF-1.4\n")], offsets=[0];
|
||||
let length=chunks[0].length;
|
||||
|
||||
Reference in New Issue
Block a user