- Rotation de pages : clic droit sur vignette → Pivoter +90/-90/180 Aussi dans le menu Pages - Ctrl+Z / Ctrl+Y : annuler et refaire (pile de 20 etats) - Delivretiser : coupe les pages en 2 et remet dans l'ordre sequentiel (inverse de la creation de livret) - Trim & Shift : decaler le contenu des pages - Decalage X/Y different pages paires/impaires - Compensation de creep progressive pour livrets epais - Inverser l'ordre des pages (menu Pages) - Fix impression : ouvre le PDF dans le lecteur par defaut - Barre outils droite : ajout Delivretiser, Trim/Shift, Inverser Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
"""Moteur Trim & Shift — decaler le contenu des pages."""
|
|
|
|
from pypdf import PdfReader, PdfWriter, PageObject, Transformation
|
|
from .pdf_utils import get_page_size
|
|
|
|
|
|
def trim_and_shift(input_path, output_path, shift_x=0, shift_y=0,
|
|
shift_x_even=None, shift_y_even=None,
|
|
creep=0, creep_pages=0):
|
|
"""Decaler le contenu des pages.
|
|
|
|
shift_x, shift_y: decalage en points (pages impaires si even specifie)
|
|
shift_x_even, shift_y_even: decalage pour pages paires (None = meme que impaires)
|
|
creep: decalage progressif en points (compensation epaisseur papier)
|
|
creep_pages: nombre total de pages pour le calcul du creep
|
|
"""
|
|
reader = PdfReader(input_path)
|
|
writer = PdfWriter()
|
|
num_pages = len(reader.pages)
|
|
|
|
if shift_x_even is None:
|
|
shift_x_even = shift_x
|
|
if shift_y_even is None:
|
|
shift_y_even = shift_y
|
|
|
|
for i, page in enumerate(reader.pages):
|
|
page_num = i + 1
|
|
w, h = get_page_size(page)
|
|
|
|
# Decalage de base
|
|
if page_num % 2 == 0:
|
|
dx, dy = shift_x_even, shift_y_even
|
|
else:
|
|
dx, dy = shift_x, shift_y
|
|
|
|
# Creep progressif (pour livrets)
|
|
if creep != 0 and creep_pages > 0:
|
|
# Les pages du centre se decalent le plus
|
|
mid = num_pages / 2
|
|
distance_from_center = abs(i - mid) / mid # 0 au centre, 1 aux bords
|
|
creep_amount = creep * (1 - distance_from_center)
|
|
if page_num % 2 == 0:
|
|
dx -= creep_amount # pages paires : decaler vers la gauche
|
|
else:
|
|
dx += creep_amount # pages impaires : decaler vers la droite
|
|
|
|
if dx != 0 or dy != 0:
|
|
new_page = PageObject.create_blank_page(width=w, height=h)
|
|
overlay = PageObject.create_blank_page(width=w, height=h)
|
|
overlay.merge_page(page)
|
|
overlay.add_transformation(Transformation().translate(dx, dy))
|
|
new_page.merge_page(overlay)
|
|
writer.add_page(new_page)
|
|
else:
|
|
writer.add_page(page)
|
|
|
|
with open(output_path, "wb") as f:
|
|
writer.write(f)
|
|
return output_path
|