import * as pdfjs from 'pdfjs-dist'; // Set worker path - using a CDN for the worker to avoid complex vite configuration for now // or we can try to use the bundled worker if vite handles it pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`; export const pdfRenderService = { async renderPageToCanvas( pdfData: Blob | ArrayBuffer, pageNumber: number, canvas: HTMLCanvasElement, targetWidth: number, targetHeight: number ): Promise { const data = pdfData instanceof Blob ? await pdfData.arrayBuffer() : pdfData; const loadingTask = pdfjs.getDocument({ data }); const pdf = await loadingTask.promise; if (pageNumber < 1 || pageNumber > pdf.numPages) { throw new Error(`Invalid page number: ${pageNumber}.`); } const page = await pdf.getPage(pageNumber); // Calculate scale to fit container while maintaining aspect ratio const unscaledViewport = page.getViewport({ scale: 1 }); // Calculate the scale needed to fit the PDF page within the target dimensions const fitScale = Math.min(targetWidth / unscaledViewport.width, targetHeight / unscaledViewport.height); // Calculate a higher scale for rendering quality (anti-aliasing and clarity) const devicePixelRatio = window.devicePixelRatio || 1; const renderScale = fitScale * Math.max(2, devicePixelRatio); const viewport = page.getViewport({ scale: renderScale }); // Set canvas to the high-resolution dimensions to maintain quality canvas.width = viewport.width; canvas.height = viewport.height; const context = canvas.getContext('2d'); if (!context) return; // Save the context state before any transformations context.save(); // Fill background context.fillStyle = '#f8fafc'; context.fillRect(0, 0, canvas.width, canvas.height); // Calculate the position to center the PDF page in the canvas const offsetX = (canvas.width - viewport.width) / 2; const offsetY = (canvas.height - viewport.height) / 2; await page.render({ canvasContext: context, viewport: viewport, transform: [1, 0, 0, 1, offsetX, offsetY] }).promise; // Restore the context state after rendering context.restore(); } };