"""Stili dei riquadri e palette colori per gravita'. Solo costanti/mappature.""" from __future__ import annotations # Stili disponibili (chiave -> etichetta IT per la UI). STYLE_LABELS: dict[str, str] = { "fill": "Pieno", "outline": "Solo bordo", "label": "Pieno + etichetta", "pixelate": "Mosaico", "blur": "Sfocato", # Stili specifici della hard redaction (fill della redazione). "black": "Neri", "color": "Colorati per gravità", } # Palette RGB [0,1] per livello di gravita' (coerente con config/severity). _SEVERITY_RGB: dict[str, tuple[float, float, float]] = { "critica": (0.86, 0.15, 0.15), "alta": (0.92, 0.35, 0.05), "media": (0.79, 0.54, 0.02), "bassa": (0.15, 0.39, 0.92), } def severity_rgb(severity: str) -> tuple[float, float, float]: return _SEVERITY_RGB.get(severity, (0.0, 0.0, 0.0)) def fit_fontsize(text: str, rect, *, max_fs: float = 11.0, min_fs: float = 4.0) -> float: """Massimo fontsize Helvetica per cui `text` sta nel box (larghezza E altezza). Le etichette tipo ([EMAIL]) sono corte, ma il mascheramento per-carattere ('R***************') è lungo quanto l'originale: il fontsize va calcolato sulla LARGHEZZA del testo, non solo sull'altezza, altrimenti il testo va in overflow e non viene disegnato. Condiviso da annotate (insert_textbox) e redact (add_redact_annot).""" import fitz if not text: return max_fs unit_w = fitz.get_text_length(text, fontname="helv", fontsize=1.0) or 1.0 fs_w = (rect.width - 2.0) / unit_w # margine orizzontale di 2pt fs_h = rect.height * 0.6 # interlinea reale del text box (~1.5×) return max(min_fs, min(max_fs, fs_w, fs_h)) def severity_rgb255(severity: str) -> tuple[int, int, int]: r, g, b = severity_rgb(severity) return int(r * 255), int(g * 255), int(b * 255)