feat(format): B3.5 — PDF smart-fit rewrite + critical fontname=None fix
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m44s

ROOT CAUSE FIX: PyMuPDF silently raised AttributeError when fontname=None
was passed to insert_textbox. The try/except in _try_insert was swallowing
the error and returning None, causing every block to be skipped via the
graceful failure path. Setting fontname='helv' as the default unblocks
the entire PDF translation pipeline.

SMART-FIT: rewrite _write_translated_block with proper tier-fallback:
  - Tier 0: original bbox at original size
  - Tier 1: expanded horizontal
  - Tier 2: expanded vertical (3x original height)
  - Tier 3: shrink once (0.93x)
  - Tier 4: shrink twice (0.87x cumulative)
  - Tier 5: min size floor (90% for headings, 75% for body)
  - Tier 6: graceful skip with visible placeholder

REDACTION: single redaction per block (was per sub-bbox, creating 100+
redaction rectangles per page). Now only 1 redaction per text block.

FEATURE FLAG: PDF_SMART_FIT_ENABLED (default true, observation-first).

METRICS: text_overflow -> format_elements_lost_total.

RESULT ON REAL PDF:
  Before: fonts shrunk 22pt->5.6pt, hierarchy destroyed
  After:  fonts EXACT match: [8, 11, 12, 14, 16, 22] preserved
This commit is contained in:
2026-07-14 18:36:12 +02:00
parent 12cd0c6893
commit e706cef5d6
16 changed files with 1294 additions and 62 deletions

40
scripts/debug_rc_real.py Normal file
View File

@@ -0,0 +1,40 @@
"""Debug: show actual rc values for the title block in real translation."""
import sys
sys.path.insert(0, '.')
import importlib.util
import fitz
from pathlib import Path
spec = importlib.util.spec_from_file_location('pdf_mod', 'translators/pdf_translator.py')
pdf_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(pdf_mod)
# Patch _try_insert to log rc values
original_try_insert = pdf_mod.PDFTranslator._try_insert
TITLES_TO_TRACE = {"Spécification technique : Office Translator v3.0", "Technical Specification: Office Translator v3.0"}
def debug_try_insert(self, page, rect, text, fontsize, fontname, fontfile, color, align):
rc = page.insert_textbox(
rect, text,
fontsize=fontsize,
fontname=fontname,
fontfile=fontfile,
color=color,
align=align,
overlay=True,
)
# Only trace the title
is_title = any(t in text for t in ["Spécification technique", "Technical Specification"])
if is_title:
print(f" [TITLE] size={fontsize:.1f} rect={rect.width:.0f}x{rect.height:.0f} -> rc={rc}", flush=True)
return rc
pdf_mod.PDFTranslator._try_insert = debug_try_insert
PDFTranslator = pdf_mod.PDFTranslator
PDFTranslator().translate_file(
Path('sample_files/test_corpus/test_pdf.pdf'),
Path('sample_files/test_corpus/test_pdf_translated.pdf'),
target_language='fr',
source_language='en',
)