fix: match reference layout geometry (margins, student row zones, column spread, spacing)

This commit is contained in:
adrianbonpin
2026-08-18 19:56:06 +08:00
parent 792974bd32
commit 57c4b6f204
+26 -28
View File
@@ -101,9 +101,9 @@
const font = doc.embedStandardFont(StandardFonts.Helvetica); const font = doc.embedStandardFont(StandardFonts.Helvetica);
const bold = doc.embedStandardFont(StandardFonts.HelveticaBold); const bold = doc.embedStandardFont(StandardFonts.HelveticaBold);
const italic = doc.embedStandardFont(StandardFonts.HelveticaOblique); const italic = doc.embedStandardFont(StandardFonts.HelveticaOblique);
const margin = 50; const margin = 36;
const contentWidth = 612 - margin * 2; const contentWidth = 612 - margin * 2; // 540; right edge = 576
let y = 792 - 50; let y = 792 - 10; // near the very top, matching the reference logo position
const black = rgb(0, 0, 0); const black = rgb(0, 0, 0);
const gray = rgb(0.3, 0.3, 0.3); const gray = rgb(0.3, 0.3, 0.3);
@@ -132,7 +132,7 @@
const logoW = 292.5; const logoW = 292.5;
const logoH = logoW * (logoImg.height / logoImg.width); const logoH = logoW * (logoImg.height / logoImg.width);
page.drawImage(logoImg, { x: (612 - logoW) / 2, y: y - logoH, width: logoW, height: logoH }); page.drawImage(logoImg, { x: (612 - logoW) / 2, y: y - logoH, width: logoW, height: logoH });
y -= logoH + 14; y -= logoH + 10;
} }
center("STUDENT'S STUDY LOAD", 9.5, bold, 16); center("STUDENT'S STUDY LOAD", 9.5, bold, 16);
if (header.semester) center(String(header.semester).toUpperCase(), 9, font, 14); if (header.semester) center(String(header.semester).toUpperCase(), 9, font, 14);
@@ -140,34 +140,32 @@
if (dateRange) center(dateRange, 9, font, 14); if (dateRange) center(dateRange, 9, font, 14);
if (header.dateEnrolled) left('Date Enrolled: ' + header.dateEnrolled, 8, italic, margin, 13); if (header.dateEnrolled) left('Date Enrolled: ' + header.dateEnrolled, 8, italic, margin, 13);
// Student info row: ID (bold), name, program (compacted), "Year Level: N" // Student info row, laid out in fixed zones across the page (matching the
const studentParts = []; // reference): ID (bold) left, name at ~100, program at ~338, and
if (header.studentId) studentParts.push({ text: header.studentId, f: bold }); // "Year Level: N" right-aligned to the right content edge (576).
if (header.fullName) studentParts.push({ text: header.fullName, f: font }); const yearLevelText = header.yearLevel ? 'Year Level: ' + header.yearLevel : '';
if (header.program) studentParts.push({ text: compactProgram(header.program), f: font }); if (header.studentId) page.drawText(header.studentId, { x: margin, y, size: 9, font: bold, color: black });
if (header.yearLevel) studentParts.push({ text: 'Year Level: ' + header.yearLevel, f: font }); if (header.fullName) page.drawText(header.fullName, { x: 100, y, size: 9, font, color: black });
if (studentParts.length) { if (header.program) page.drawText(compactProgram(header.program), { x: 338, y, size: 9, font, color: black });
let sx = margin; if (yearLevelText) {
for (const part of studentParts) { const w = font.widthOfTextAtSize(yearLevelText, 9);
const w = part.f.widthOfTextAtSize(part.text, 9); page.drawText(yearLevelText, { x: margin + contentWidth - w, y, size: 9, font, color: black });
page.drawText(part.text, { x: sx, y, size: 9, font: part.f, color: black });
sx += w + 18;
}
y -= 16;
} }
if (header.studentId || header.fullName || header.program || yearLevelText) y -= 16;
// ---- Table: GROUP, COURSE, COURSE DESCRIPTION, TEACHER, UNITS, NOTE ---- // ---- Table: GROUP, COURSE, COURSE DESCRIPTION, TEACHER, UNITS, NOTE ----
// Column left edges + widths, tuned to the reference geometry (right edge 576).
const cols = [ const cols = [
{ key: 'group', label: 'GROUP', x: margin, w: 26, align: 'left' }, { key: 'group', label: 'GROUP', x: margin, w: 38, align: 'left' },
{ key: 'courseCode', label: 'COURSE', x: margin + 26, w: 46, align: 'left' }, { key: 'courseCode', label: 'COURSE', x: margin + 38, w: 42, align: 'left' },
{ key: 'description', label: 'COURSE DESCRIPTION', x: margin + 72, w: 189, align: 'left' }, { key: 'description', label: 'COURSE DESCRIPTION', x: margin + 80, w: 201, align: 'left' },
{ key: 'teacher', label: 'TEACHER', x: margin + 261, w: 123, align: 'left' }, { key: 'teacher', label: 'TEACHER', x: margin + 281, w: 128, align: 'left' },
{ key: 'units', label: 'UNITS', x: margin + 384, w: 31, align: 'right' }, { key: 'units', label: 'UNITS', x: margin + 409, w: 31, align: 'right' },
{ key: 'status', label: 'NOTE', x: margin + 415, w: 97, align: 'right' } { key: 'status', label: 'NOTE', x: margin + 440, w: 100, align: 'right' }
]; ];
const cellSize = 8; const cellSize = 8;
const headerSize = 8; const headerSize = 8;
const lineH = 10; const lineH = 12;
function rowLines(cells) { function rowLines(cells) {
return cols.map((c) => { return cols.map((c) => {
@@ -187,11 +185,11 @@
const f = isHeader ? bold : font; const f = isHeader ? bold : font;
const size = isHeader ? headerSize : cellSize; const size = isHeader ? headerSize : cellSize;
const linesPerCol = rowLines(cells); const linesPerCol = rowLines(cells);
const rowHeight = Math.max(...linesPerCol.map((l) => l.length)) * lineH + 8; const rowHeight = Math.max(...linesPerCol.map((l) => l.length)) * lineH + 12;
if (y - rowHeight < 50) { if (y - rowHeight < 50) {
page = doc.addPage([612, 792]); page = doc.addPage([612, 792]);
y = 792 - 50; y = 792 - 10;
drawHeaderRow(); drawHeaderRow();
} }
@@ -246,7 +244,7 @@
// ---- Footer ---- // ---- Footer ----
if (y < 90) { if (y < 90) {
page = doc.addPage([612, 792]); page = doc.addPage([612, 792]);
y = 792 - 50; y = 792 - 10;
} }
y -= 8; y -= 8;
if (data.totalUnits) { if (data.totalUnits) {