Files
sliding-automation/patch_render_engine_c3b.py
T

174 lines
7.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
patch_render_engine_c3b.py — Chantier C3b (centrage vertical)
=============================================================
Corrige deux défauts de centrage vertical révélés par les previews C2,
SANS toucher au helper _cy() (le centrage du contenu dans la zone est
un choix de design assumé — le contenu respire).
P1. big_stat : la hauteur de bloc était codée en dur (block = 8.13),
sous-estimée par rapport au placement réel (chiffre à y, desc à
y+5.33, source à y+7.37 ≈ 8.3+). Résultat : _cy() centrait un
bloc faussé, l'ensemble penchait vers le bas. Correctif : hauteur
réelle calculée (avec/sans source) → centrage exact. Les offsets
internes deviennent relatifs à cette hauteur.
P2. executive_summary : dans chaque carte (hauteur ch=3.68), le label
et le texte étaient posés à des offsets FIXES (y+0.56, y+1.57),
collés en haut, laissant du vide en bas de carte. Correctif : le
bloc label+texte est centré verticalement dans la carte (offsets
dérivés de ch), à côté du badge déjà centré.
Aucune dépendance nouvelle ; réutilise measure via estimate_text_height
déjà présent. Vérifie chaque ancre, écrit .bak-c3b, compile, idempotent.
Usage (dossier du pipeline, single-line) :
python3 patch_render_engine_c3b.py
"""
import py_compile
import shutil
import sys
from pathlib import Path
TARGET = Path("render_engine_v2.py")
PATCHES = [
# P1 — big_stat : hauteur réelle
(
' def _render_big_stat(self, slide, d):\n'
' self._title(slide, pick(d, "titre", "title"))\n'
' val = pick(d, "valeur", "stat", "chiffre", "value")\n'
' desc = pick(d, "description", "texte", "label")\n'
' src = pick(d, "source", "reference")\n'
' block = 8.13\n'
' y = self._cy(block)\n'
' self._text(slide, 0, y, self.SLIDE_W, 5.1, val,\n'
' font=self.F_DISPLAY, size=self.T["stat_hero"], '
'bold=True,\n'
' color=self.C["coral"], align=PP_ALIGN.CENTER,\n'
' anchor=MSO_ANCHOR.MIDDLE)\n'
' self._text(slide, 6.86, y + 5.33, self.SLIDE_W - 13.72, '
'2.0, desc,\n'
' size=18, color=self.C["body"], '
'align=PP_ALIGN.CENTER)\n'
' if src:\n'
' self._text(slide, 6.86, y + 7.37, self.SLIDE_W - '
'13.72, 0.9, src,\n'
' size=11, italic=True, '
'color=self.C["muted"],\n'
' align=PP_ALIGN.CENTER)\n',
' def _render_big_stat(self, slide, d):\n'
' self._title(slide, pick(d, "titre", "title"))\n'
' val = pick(d, "valeur", "stat", "chiffre", "value")\n'
' desc = pick(d, "description", "texte", "label")\n'
' src = pick(d, "source", "reference")\n'
' # Hauteur réelle du bloc (C3b) : chiffre + desc '
'(+ source)\n'
' H_VAL, GAP_D, H_DESC, GAP_S, H_SRC = 5.1, 0.23, 2.0, '
'0.14, 0.9\n'
' block = H_VAL + GAP_D + H_DESC + (\n'
' GAP_S + H_SRC if src else 0.0)\n'
' y = self._cy(block)\n'
' self._text(slide, 0, y, self.SLIDE_W, H_VAL, val,\n'
' font=self.F_DISPLAY, size=self.T["stat_hero"], '
'bold=True,\n'
' color=self.C["coral"], align=PP_ALIGN.CENTER,\n'
' anchor=MSO_ANCHOR.MIDDLE)\n'
' y_desc = y + H_VAL + GAP_D\n'
' self._text(slide, 6.86, y_desc, self.SLIDE_W - 13.72, '
'H_DESC, desc,\n'
' size=18, color=self.C["body"], '
'align=PP_ALIGN.CENTER)\n'
' if src:\n'
' y_src = y_desc + H_DESC + GAP_S\n'
' self._text(slide, 6.86, y_src, self.SLIDE_W - 13.72, '
'H_SRC, src,\n'
' size=11, italic=True, '
'color=self.C["muted"],\n'
' align=PP_ALIGN.CENTER)\n',
),
# P2 — executive_summary : bloc label+texte centré dans la carte
(
' self._text(slide, self.MX + 3.81, y + 0.56, 8.1, 1.0, '
'label,\n'
' size=14, bold=True, color=col, '
'char_spacing=3)\n'
' self._text(slide, self.MX + 3.81, y + 1.57,\n'
' self.SLIDE_W - 2 * self.MX - 5.33, 1.8, '
'txt,\n'
' size=self.T["body"], '
'color=self.C["body"])\n',
' # Bloc label+texte centré verticalement dans la carte '
'(C3b)\n'
' H_LBL, GAP_LT, H_TXT = 0.85, 0.18, 1.8\n'
' blk = H_LBL + GAP_LT + H_TXT\n'
' y_lbl = y + max(0.0, (ch - blk) / 2)\n'
' self._text(slide, self.MX + 3.81, y_lbl, 8.1, H_LBL, '
'label,\n'
' size=14, bold=True, color=col, '
'char_spacing=3,\n'
' anchor=MSO_ANCHOR.MIDDLE)\n'
' self._text(slide, self.MX + 3.81, y_lbl + H_LBL + '
'GAP_LT,\n'
' self.SLIDE_W - 2 * self.MX - 5.33, H_TXT, '
'txt,\n'
' size=self.T["body"], color=self.C["body"],'
'\n'
' anchor=MSO_ANCHOR.MIDDLE)\n',
),
]
MARKER = "Hauteur réelle du bloc (C3b)"
def fail(msg):
print(" ! %s" % msg)
sys.exit(1)
def main():
if not TARGET.exists():
fail("%s introuvable — lancer depuis le dossier du pipeline."
% TARGET)
content = TARGET.read_text(encoding="utf-8")
if MARKER in content:
fail("Déjà patché (C3b présent) — rien à faire.")
for i, (old, _) in enumerate(PATCHES, 1):
n = content.count(old)
if n == 0:
fail("Ancre du patch %d introuvable — moteur inattendu "
"(version différente ?)." % i)
if n > 1:
fail("Ancre du patch %d non unique (%d occurrences)." % (i, n))
shutil.copy2(TARGET, str(TARGET) + ".bak-c3b")
print(" + Sauvegarde : %s.bak-c3b" % TARGET)
for old, new in PATCHES:
content = content.replace(old, new)
TARGET.write_text(content, encoding="utf-8")
print(" + 2 patchs de centrage appliqués (big_stat, "
"executive_summary).")
try:
py_compile.compile(str(TARGET), doraise=True)
print(" + Compilation OK.")
except py_compile.PyCompileError as e:
shutil.copy2(str(TARGET) + ".bak-c3b", TARGET)
fail("Erreur de compilation — fichier restauré :\n%s" % e)
print("\n Re-rends et compare les previews : big_stat (chiffre "
"mieux centré),")
print(" executive_summary (texte centré dans les cartes). Vérifie "
"aussi from_to_pairs")
print(" (le rognage des labels a pu disparaître avec le fix polices "
"C3).")
if __name__ == "__main__":
main()