File size: 6,196 Bytes
34bcbf8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
 * pdf-generator.js
 * Generates High-Resolution Image PDF using html2canvas 
 * to preserve exact Devanagari ligatures and fonts,
 * optimized for 2-5MB file sizes via JPEG compression.
 */

function generateAadhaarPDF() {
    return new Promise((resolve, reject) => {
        const { jsPDF } = window.jspdf;

        const now = new Date();
        const timeStamp = `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;
        
        const nameInput = document.getElementById('in-name-en');
        const nameVal = nameInput && nameInput.value ? nameInput.value.trim().replace(/\s+/g, '_') : 'Applicant';
        const fileName = `${nameVal}_Aadhaar_${timeStamp}.pdf`;

        const ws = document.getElementById('workspace');
        const previewArea = document.querySelector('.preview-area');
        
        // Show preview area off-screen so html2canvas can capture it
        const originalPreviewDisplay = previewArea ? previewArea.style.display : '';
        const originalPreviewPosition = previewArea ? previewArea.style.position : '';
        const originalPreviewLeft = previewArea ? previewArea.style.left : '';
        if (previewArea) {
            previewArea.style.setProperty('display', 'flex', 'important');
            previewArea.style.position = 'fixed';
            previewArea.style.left = '-9999px';
            previewArea.style.top = '0';
        }

        // Temporarily remove scale transforms so html2canvas captures full A4 layout
        const originalTransform = ws.style.transform;
        const originalShadow = ws.style.boxShadow;
        ws.style.transform = 'none';
        ws.style.boxShadow = 'none';

        // FIX: html2canvas blurs "background-size: cover" CSS images and misaligns them
        // Calculate precise mathematical dimensions mirroring 'cover' logic in mm natively
        const bgImgNative = new Image();

        bgImgNative.onload = () => {
        const pageRatio = 210 / 297;
        const imgRatio = bgImgNative.naturalWidth / bgImgNative.naturalHeight;
        let drawW, drawH, drawX, drawY;

        if (imgRatio > pageRatio) {
            drawH = 297;
            drawW = (297 / bgImgNative.naturalHeight) * bgImgNative.naturalWidth;
            drawX = (210 - drawW) / 2;
            drawY = 0;
        } else {
            drawW = 210;
            drawH = (210 / bgImgNative.naturalWidth) * bgImgNative.naturalHeight;
            drawX = 0;
            drawY = (297 - drawH) / 2;
        }

        bgImgNative.style.position = 'absolute';
        bgImgNative.style.width = drawW + 'mm';
        bgImgNative.style.height = drawH + 'mm';
        bgImgNative.style.left = drawX + 'mm';
        bgImgNative.style.top = drawY + 'mm';
        bgImgNative.style.objectFit = 'fill';
        bgImgNative.style.zIndex = '0';
        bgImgNative.id = 'temp-bg-native';

        const originalBgLayer = document.querySelector('.bg-layer');
        const oldDisplay = originalBgLayer ? originalBgLayer.style.display : '';
        if (originalBgLayer) originalBgLayer.style.display = 'none';
        ws.prepend(bgImgNative);

        // Timeout ensures DOM repaints before capture
        setTimeout(() => {
            html2canvas(ws, {
                scale: 4, // 7x scale increases Sharpness dramatically and lands around ~5-8MB resulting JPEG size
                useCORS: true,
                allowTaint: true,
                backgroundColor: '#ffffff',
                logging: false,
                onclone: (clonedDoc) => {
                    const clonedWs = clonedDoc.getElementById('workspace');
                    if (clonedWs) {
                        clonedWs.style.transform = 'none';
                        clonedWs.style.boxShadow = 'none';
                    }

                    // Force exact 6.3pt (8.4px) on requested text elements inside the cloned capturing DOM!
                    const exactEls = clonedDoc.querySelectorAll('.inroltext, .hindi-name, .english-name, .dob-text, .gender-text, .address-hi-text, .address-en-text, .address-hi-label, .address-en-label');
                    exactEls.forEach(el => {
                        el.style.fontSize = '8.4px';
                    });
                }
            }).then(canvas => {
                // Restore UI immediately
                ws.style.transform = originalTransform;
                ws.style.boxShadow = originalShadow;
                if (originalBgLayer) originalBgLayer.style.display = oldDisplay;
                const tempBg = document.getElementById('temp-bg-native');
                if (tempBg) tempBg.remove();

                // Restore preview area state
                if (previewArea) {
                    previewArea.style.removeProperty('display');
                    previewArea.style.position = originalPreviewPosition;
                    previewArea.style.left = originalPreviewLeft;
                    previewArea.style.top = '';
                }

                // JPEG encoding at 1.0 provides the absolute maximum fidelity
                const imgData = canvas.toDataURL('image/jpeg', 1.0);
                const doc = new jsPDF('portrait', 'mm', 'a4');
                doc.addImage(imgData, 'JPEG', 0, 0, 210, 297);
                doc.save(fileName);
                resolve(fileName);

            }).catch(err => {
                console.error("PDF Generation Error:", err);
                ws.style.transform = originalTransform;
                ws.style.boxShadow = originalShadow;
                if (originalBgLayer) originalBgLayer.style.display = oldDisplay;
                const tempBg = document.getElementById('temp-bg-native');
                if (tempBg) tempBg.remove();

                if (previewArea) {
                    previewArea.style.removeProperty('display');
                    previewArea.style.position = originalPreviewPosition;
                    previewArea.style.left = originalPreviewLeft;
                    previewArea.style.top = '';
                }
                reject(err);
            });
        }, 150);
    };
    bgImgNative.src = EMBEDDED_BG;
    });
}