From 762b31083e334a87de7b034f2b2a1fdf70c97d84 Mon Sep 17 00:00:00 2001 From: stephan Date: Sat, 25 Jul 2026 10:08:52 -0400 Subject: [PATCH] Refactor dossard PDF layout to implement independent boxes for number and name, enhancing text centering and positioning. Update layout calculations for improved alignment and dynamic font sizing based on available space. Enhance comments for clarity. Increment version code. --- php/inc_fx_dossard_print.php | 156 +++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 62 deletions(-) diff --git a/php/inc_fx_dossard_print.php b/php/inc_fx_dossard_print.php index 9b44854..d55be31 100644 --- a/php/inc_fx_dossard_print.php +++ b/php/inc_fx_dossard_print.php @@ -173,7 +173,7 @@ function fxDossardPrintBuildQrTempFile($intEveId) /** * Layout calibré pour le fond comic default (8.5" × 5.5"). - * Zone en % de page — seuls leviers à toucher pour ce template. + * Deux boîtes indépendantes en % de page (références user annotées). * * @return array */ @@ -183,32 +183,34 @@ function fxDossardPrintLayout() $fltW = $arrSize[0]; $fltH = $arrSize[1]; - // Calibré pour assets/dossard_templates/default.jpg (blanc central) - $fltZoneLeftPct = 0.17; - $fltZoneRightPct = 0.80; - $fltZoneTopPct = 0.26; - $fltZoneBottomPct = 0.84; + // --- Boîte NUMÉRO (grande, rouge) --- + $arrBibPct = array( + 'left' => 0.18, + 'right' => 0.80, + 'top' => 0.34, + 'bottom' => 0.70, + ); + // --- Boîte PRÉNOM (petite, rouge) --- + $arrNamePct = array( + 'left' => 0.30, + 'right' => 0.70, + 'top' => 0.74, + 'bottom' => 0.86, + ); - $fltZoneX = $fltW * $fltZoneLeftPct; - $fltZoneY = $fltH * $fltZoneTopPct; - $fltZoneW = $fltW * ($fltZoneRightPct - $fltZoneLeftPct); - $fltZoneH = $fltH * ($fltZoneBottomPct - $fltZoneTopPct); + $arrBib = fxDossardPrintBoxFromPct($fltW, $fltH, $arrBibPct); + $arrName = fxDossardPrintBoxFromPct($fltW, $fltH, $arrNamePct); $fltQr = 28.0; return array( 'page_w' => $fltW, 'page_h' => $fltH, - 'zone_x' => $fltZoneX, - 'zone_y' => $fltZoneY, - 'zone_w' => $fltZoneW, - 'zone_h' => $fltZoneH, - // Sous la baseline du n° (chiffres ≈ sans jambage) - 'name_gap_mm' => 0.8, - 'name_font' => 17, - // Ascent Helvetica Bold ≈ 0.72 em (em = FontSize en mm) + 'bib' => $arrBib, + 'name' => $arrName, 'ascent_ratio' => 0.72, 'bib_font_max' => 220, + 'name_font_max' => 28, 'qr_size' => $fltQr, 'qr_x' => $fltW - $fltQr - 11.5, 'qr_y' => $fltH - $fltQr - 14.5, @@ -216,28 +218,49 @@ function fxDossardPrintLayout() } /** - * Plus grande police Helvetica Bold qui tient en largeur ET ascent (mm). + * Rectangle mm depuis fractions 0–1 de la page. + * + * @param float $fltPageW + * @param float $fltPageH + * @param array $arrPct left|right|top|bottom + * @return array{x:float,y:float,w:float,h:float} + */ +function fxDossardPrintBoxFromPct($fltPageW, $fltPageH, $arrPct) +{ + $fltX = $fltPageW * floatval($arrPct['left']); + $fltY = $fltPageH * floatval($arrPct['top']); + $fltW = $fltPageW * (floatval($arrPct['right']) - floatval($arrPct['left'])); + $fltH = $fltPageH * (floatval($arrPct['bottom']) - floatval($arrPct['top'])); + + return array( + 'x' => $fltX, + 'y' => $fltY, + 'w' => $fltW, + 'h' => $fltH, + ); +} + +/** + * Plus grande police Helvetica Bold qui tient dans une boîte (largeur + hauteur). * * @param FPDF $pdf - * @param string $strBib + * @param string $strText * @param float $fltMaxW - * @param float $fltMaxAscentMm + * @param float $fltMaxH * @param int $intFontMax * @param float $fltAscentRatio * @return int */ -function fxDossardPrintFitBibFont($pdf, $strBib, $fltMaxW, $fltMaxAscentMm, $intFontMax, $fltAscentRatio = 0.72) +function fxDossardPrintFitBibFont($pdf, $strText, $fltMaxW, $fltMaxH, $intFontMax, $fltAscentRatio = 0.72) { - $strPdf = fxDossardPrintPdfText($strBib); + $strPdf = fxDossardPrintPdfText($strText); $fltAscentRatio = ($fltAscentRatio > 0) ? $fltAscentRatio : 0.72; - // FontSize mm = pt * 25.4/72 ; ascent = FontSizeMm * ratio - // → pt_max = maxAscent / (ratio * 25.4/72) $fltPtPerMm = 72 / 25.4; - $intCapByH = ($fltMaxAscentMm > 0) - ? (int)floor($fltMaxAscentMm * $fltPtPerMm / $fltAscentRatio) + $intCapByH = ($fltMaxH > 0) + ? (int)floor($fltMaxH * $fltPtPerMm / $fltAscentRatio) : intval($intFontMax); - $intHi = max(24, min(intval($intFontMax), $intCapByH)); - $intLo = 24; + $intHi = max(12, min(intval($intFontMax), $intCapByH)); + $intLo = 12; $intBest = $intLo; while ($intLo <= $intHi) { @@ -254,6 +277,28 @@ function fxDossardPrintFitBibFont($pdf, $strBib, $fltMaxW, $fltMaxAscentMm, $int return $intBest; } +/** + * Texte centré dans une boîte (Cell = centre H + V FPDF). + * + * @param FPDF $pdf + * @param array $arrBox x,y,w,h + * @param string $strText + * @param int $intFont + */ +function fxDossardPrintDrawCenteredInBox($pdf, $arrBox, $strText, $intFont) +{ + $pdf->SetFont('Helvetica', 'B', $intFont); + $pdf->SetXY($arrBox['x'], $arrBox['y']); + $pdf->Cell( + $arrBox['w'], + $arrBox['h'], + fxDossardPrintPdfText($strText), + 0, + 0, + 'C' + ); +} + /** * Génère et envoie le PDF (exit). * @@ -288,9 +333,8 @@ function fxDossardPrintOutputPdf($arrRow) if ($strBib === '' || $strBib === '0') { $strBib = '-'; } - // MSIN-4485 — prénom seul, collé sous le n°, même X que le 1er chiffre. + // MSIN-4485 — prénom seul, centré dans sa boîte (%). $strName = trim(function_exists('fxUnescape') ? fxUnescape($arrRow['par_prenom'] ?? '') : (string)($arrRow['par_prenom'] ?? '')); - $blnHasName = ($strName !== ''); $strQrFile = fxDossardPrintBuildQrTempFile($intEveId); $strTplType = fxDossardPrintImageType($strTemplate); @@ -309,44 +353,32 @@ function fxDossardPrintOutputPdf($arrRow) $strTplType ); - $fltAscentRatio = $arrLayout['ascent_ratio']; - $fltNameReserve = $blnHasName ? ($arrLayout['name_gap_mm'] + 6.0) : 0; - $fltMaxAscent = max(20, $arrLayout['zone_h'] - $fltNameReserve); - $pdf->SetTextColor(0, 0, 0); + + // 1) Numéro → grande boîte, centré, police max + $arrBibBox = $arrLayout['bib']; $intBibFont = fxDossardPrintFitBibFont( $pdf, $strBib, - $arrLayout['zone_w'], - $fltMaxAscent, + $arrBibBox['w'] * 0.98, + $arrBibBox['h'] * 0.92, $arrLayout['bib_font_max'], - $fltAscentRatio + $arrLayout['ascent_ratio'] ); - $pdf->SetFont('Helvetica', 'B', $intBibFont); + fxDossardPrintDrawCenteredInBox($pdf, $arrBibBox, $strBib, $intBibFont); - $strBibPdf = fxDossardPrintPdfText($strBib); - $fltBibTextW = $pdf->GetStringWidth($strBibPdf); - // FontSize en mm (FPDF : 1 pt = 1/72") - $fltFontSizeMm = $intBibFont * 25.4 / 72; - $fltAscentMm = $fltFontSizeMm * $fltAscentRatio; - - // Bloc n° + prénom centré dans la zone - $fltBlockH = $fltAscentMm + ($blnHasName ? ($arrLayout['name_gap_mm'] + 6.0) : 0); - $fltBlockTop = $arrLayout['zone_y'] + max(0, ($arrLayout['zone_h'] - $fltBlockH) / 2); - - // X = bord gauche du premier chiffre (n° centré dans la zone) - $fltBibX = $arrLayout['zone_x'] + ($arrLayout['zone_w'] - $fltBibTextW) / 2; - // Text() : Y = baseline → bas des chiffres ≈ baseline - $fltBibBaseline = $fltBlockTop + $fltAscentMm; - - $pdf->Text($fltBibX, $fltBibBaseline, $strBibPdf); - - if ($blnHasName) { - $pdf->SetFont('Helvetica', 'B', intval($arrLayout['name_font'])); - // Collé sous la baseline (= sous le chiffre) - $fltNameBaseline = $fltBibBaseline + $arrLayout['name_gap_mm'] - + (intval($arrLayout['name_font']) * 25.4 / 72 * 0.72); - $pdf->Text($fltBibX, $fltNameBaseline, fxDossardPrintPdfText($strName)); + // 2) Prénom → petite boîte, centré, police max + if ($strName !== '') { + $arrNameBox = $arrLayout['name']; + $intNameFont = fxDossardPrintFitBibFont( + $pdf, + $strName, + $arrNameBox['w'] * 0.95, + $arrNameBox['h'] * 0.90, + $arrLayout['name_font_max'], + $arrLayout['ascent_ratio'] + ); + fxDossardPrintDrawCenteredInBox($pdf, $arrNameBox, $strName, $intNameFont); } if ($strQrFile !== false) {