Skip to content

Commit 9d15509

Browse files
Daniel CrooksDaniel Crooks
authored andcommitted
Feat: Add PDF report generation to Glyph Inspector
1 parent 19eb1e0 commit 9d15509

2 files changed

Lines changed: 173 additions & 2 deletions

File tree

index.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@
215215
</div>
216216
</div>
217217
<div>
218-
<p>Copyright © 2024 - All rights reserved by Crooks Design.</p>
218+
<p>Copyright © 2026 - All rights reserved by Crooks Design.</p>
219219
</div>
220220
</footer>
221221
<script src="src/index.js" charset="utf-8"></script>
@@ -295,7 +295,10 @@ <h3 class="text-lg font-bold">Disclaimer</h3>
295295
<input type="checkbox" id="visualize-modal" class="modal-toggle" />
296296
<label for="visualize-modal" class="modal cursor-pointer">
297297
<label class="modal-box relative" style="max-width: none; width: auto;" for="">
298-
<h3 class="text-lg font-bold" id="visualize-title">Glyph Inspector</h3>
298+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
299+
<h3 class="text-lg font-bold" id="visualize-title">Glyph Inspector</h3>
300+
<button class="btn btn-sm btn-primary" onclick="printReport()">Print PDF Report</button>
301+
</div>
299302
<div class="flex flex-row flex-wrap lg:flex-nowrap justify-center p-4" style="gap: 2em;">
300303
<div class="text-center">
301304
<h4 class="font-bold text-xl mb-2">I</h4>

src/index.js

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,11 @@ function updateTableRows() {
218218
});
219219
}
220220

221+
let currentFontIndex = -1;
222+
221223
// Visualization Logic
222224
window.showVisualization = function(index) {
225+
currentFontIndex = index;
223226
const result = window.processedFonts[index];
224227
if (!result) return;
225228

@@ -235,6 +238,171 @@ window.showVisualization = function(index) {
235238
updateInfo('info-o', result.o);
236239
}
237240

241+
window.printReport = function() {
242+
if (currentFontIndex === -1) return;
243+
const result = window.processedFonts[currentFontIndex];
244+
245+
const canvasI = document.getElementById('canvas-i').toDataURL('image/png');
246+
const canvasH = document.getElementById('canvas-h').toDataURL('image/png');
247+
const canvasO = document.getElementById('canvas-o').toDataURL('image/png');
248+
249+
function getPoints(char) {
250+
if (!result.original) return '';
251+
const path = result.original.getPath(char, 0, 150, 72);
252+
return path.commands.filter(c => c.x !== undefined && c.y !== undefined)
253+
.map(c => `(${Math.round(c.x)}, ${Math.round(c.y)})`).join(', ');
254+
}
255+
256+
const ptsI = getPoints('I');
257+
const ptsH = getPoints('H');
258+
const ptsO = getPoints('O');
259+
260+
const w = window.open('', '_blank');
261+
w.document.write(`
262+
<html>
263+
<head>
264+
<title>ADAFontCheck Report - ${result.name}</title>
265+
<style>
266+
body { font-family: sans-serif; font-size: 12px; padding: 20px; max-width: 800px; margin: 0 auto; }
267+
h1 { margin-bottom: 5px; font-size: 18px; }
268+
.header { display: flex; justify-content: space-between; border-bottom: 2px solid #333; padding-bottom: 10px; margin-bottom: 15px; align-items: flex-end; }
269+
.timestamp { font-size: 0.9em; color: #666; }
270+
.watermark { font-weight: bold; font-size: 14px; }
271+
.watermark a { color: #0369a1; text-decoration: none; }
272+
.disclaimer { font-size: 0.75em; color: #777; margin-top: 30px; border-top: 1px solid #eee; padding-top: 10px; line-height: 1.3; }
273+
.compliance { font-size: 0.75em; color: #555; margin-top: 10px; line-height: 1.3; }
274+
.compliance a { color: #0369a1; }
275+
.section { margin-bottom: 15px; display: flex; align-items: flex-start; gap: 20px; border-bottom: 1px solid #f0f0f0; padding-bottom: 15px; break-inside: avoid; }
276+
.canvas-container { text-align: center; }
277+
.canvas-img { border: 1px solid #ddd; width: 140px; height: 140px; object-fit: contain; background: #fff; }
278+
.glyph-label { font-weight: bold; font-size: 16px; margin-top: 5px; }
279+
.metrics { flex: 1; }
280+
.coords-label { font-weight: bold; margin-top: 5px; display: block; font-size: 0.9em; }
281+
.coords { font-family: monospace; font-size: 0.85em; color: #444; word-break: break-all; line-height: 1.4; }
282+
.status-pass { color: green; font-weight: bold; }
283+
.status-fail { color: red; font-weight: bold; }
284+
.results-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
285+
.results-table th, .results-table td { border: 1px solid #ccc; padding: 6px 10px; text-align: left; font-size: 11px; }
286+
.results-table th { background: #f2f2f2; }
287+
.req-info { font-weight: normal; font-size: 0.85em; color: #666; display: block; margin-top: 2px; }
288+
@media print {
289+
body { padding: 0; }
290+
button { display: none; }
291+
}
292+
</style>
293+
</head>
294+
<body>
295+
<div class="header">
296+
<div>
297+
<h1>${result.name}</h1>
298+
<div class="timestamp">${new Date().toLocaleString()}</div>
299+
</div>
300+
<div class="watermark"><a href="https://adafontcheck.xyz">adafontcheck.xyz</a></div>
301+
</div>
302+
303+
<div class="results">
304+
<h3 style="margin-top:0;">Compliance Summary</h3>
305+
<table class="results-table">
306+
<tr>
307+
<th>Test</th>
308+
<th>Federal Requirements</th>
309+
<th>California Requirements</th>
310+
</tr>
311+
<tr>
312+
<td>
313+
<strong>Tactile</strong><br>
314+
<small>Measured - Stroke: ${result.stroke.ratio}%, Body: ${result.body.ratio}%</small>
315+
</td>
316+
<td class="${result.test.federal.tactile ? 'status-pass' : 'status-fail'}">
317+
${result.test.federal.tactile ? 'PASS' : 'FAIL'}
318+
<span class="req-info">Body: 55-110%, Stroke: 0-15%</span>
319+
</td>
320+
<td class="${result.test.california.tactile ? 'status-pass' : 'status-fail'}">
321+
${result.test.california.tactile ? 'PASS' : 'FAIL'}
322+
<span class="req-info">Body: 60-110%, Stroke: 0-15%</span>
323+
</td>
324+
</tr>
325+
<tr>
326+
<td>
327+
<strong>Visual</strong><br>
328+
<small>Measured - Stroke: ${result.stroke.ratio}%, Body: ${result.body.ratio}%</small>
329+
</td>
330+
<td class="${result.test.federal.visual ? 'status-pass' : 'status-fail'}">
331+
${result.test.federal.visual ? 'PASS' : 'FAIL'}
332+
<span class="req-info">Body: 55-110%, Stroke: 10-30%</span>
333+
</td>
334+
<td class="${result.test.california.visual ? 'status-pass' : 'status-fail'}">
335+
${result.test.california.visual ? 'PASS' : 'FAIL'}
336+
<span class="req-info">Body: 60-110%, Stroke: 10-20%</span>
337+
</td>
338+
</tr>
339+
</table>
340+
</div>
341+
342+
<div class="section">
343+
<div class="canvas-container">
344+
<img src="${canvasI}" class="canvas-img">
345+
<div class="glyph-label">I</div>
346+
</div>
347+
<div class="metrics">
348+
<strong>Stroke Width Ratio:</strong> ${result.i.ratio}% <br>
349+
Width: ${result.i.width ? result.i.width.toFixed(2) : 'N/A'}, Height: ${result.i.height ? result.i.height.toFixed(2) : 'N/A'}
350+
<span class="coords-label">Coordinates (Green Dots):</span>
351+
<div class="coords">${ptsI}</div>
352+
</div>
353+
</div>
354+
355+
<div class="section">
356+
<div class="canvas-container">
357+
<img src="${canvasH}" class="canvas-img">
358+
<div class="glyph-label">H</div>
359+
</div>
360+
<div class="metrics">
361+
<strong>Body Width Ratio:</strong> ${result.h.ratio}% <br>
362+
Width: ${result.h.width ? result.h.width.toFixed(2) : 'N/A'}, Height: ${result.h.height ? result.h.height.toFixed(2) : 'N/A'}
363+
<span class="coords-label">Coordinates (Green Dots):</span>
364+
<div class="coords">${ptsH}</div>
365+
</div>
366+
</div>
367+
368+
<div class="section" style="border-bottom: none;">
369+
<div class="canvas-container">
370+
<img src="${canvasO}" class="canvas-img">
371+
<div class="glyph-label">O</div>
372+
</div>
373+
<div class="metrics">
374+
<strong>Body Width Ratio:</strong> ${result.o.ratio}% <br>
375+
Width: ${result.o.width ? result.o.width.toFixed(2) : 'N/A'}, Height: ${result.o.height ? result.o.height.toFixed(2) : 'N/A'}
376+
<span class="coords-label">Coordinates (Green Dots):</span>
377+
<div class="coords">${ptsO}</div>
378+
</div>
379+
</div>
380+
381+
<div class="disclaimer">
382+
<strong>Disclaimer:</strong> ADAFontCheck is not endorsed by the United States Access Board or anyone else. The creators of ADAFontCheck assume no liability or responsibility whatsoever for any direct, indirect, special, or other consequential damages relating to any use of this online service or the contents of this website. Use at your own discretion with confidence.
383+
</div>
384+
385+
<div class="compliance">
386+
This service is based on <a href="https://archive.ada.gov/regs2010/2010ADAStandards/2010ADAStandards.pdf">2010 Americans with Disabilities Act Accessibility Guidelines</a> and <a href="https://up.codes/viewer/california/ibc-2018/chapter/new_11B/accessibility-to-public-buildings-public-accommodations-commercial-buildings-and#new_11B-703">2019 California Building Standards Code</a>.
387+
</div>
388+
389+
<div style="margin-top: 30px; text-align: center; font-size: 0.8em; color: #555; padding: 10px; border-top: 1px solid #ddd;">
390+
Copyright © 2026 - All rights reserved by Crooks Design.
391+
</div>
392+
393+
<script>
394+
window.onload = function() {
395+
setTimeout(function() {
396+
window.print();
397+
}, 500);
398+
}
399+
</script>
400+
</body>
401+
</html>
402+
`);
403+
w.document.close();
404+
}
405+
238406
function updateInfo(id, metrics) {
239407
const el = document.getElementById(id);
240408
if(el) {

0 commit comments

Comments
 (0)