V3.6.0 — Demonter pages, masquage visuel, regles, bleeds, corrections

- Demonter les pages : couper en 2 sans reordonner (sous Delivretiser)
- Masquage visuel : selection au curseur sur l'apercu + plage de pages
- Regles horizontale/verticale en mm (menu Affichage)
- Fonds perdus : filigrane rouge pour visualiser les bleeds
- Reperes de coupe : marques a l'exterieur (page agrandie), 2 traits/coin
- Numerotation : couleur configurable via selecteur
- Decalage : Trim & Shift renomme en francais, creep -> chasse
- Recadrages multiples cumulatifs (plages differentes)
- Fix spinbox format personnalise (fleches aleatoires)
- Fix combo livret : option Automatique preservee

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jules
2026-03-29 22:12:54 +02:00
parent f7ad806b26
commit 202834a794
13 changed files with 675 additions and 113 deletions

View File

@@ -1,6 +1,6 @@
"""Moteur Reperes de coupe autonomes."""
from pypdf import PdfReader, PdfWriter
from pypdf import PdfReader, PdfWriter, PageObject, Transformation
from reportlab.pdfgen import canvas
from .pdf_utils import get_page_size
import io
@@ -8,11 +8,18 @@ import io
def add_crop_marks(input_path, output_path, mark_length=14.17, mark_offset=7.09,
line_width=0.25, color=(0, 0, 0), center_marks=False,
apply_to="all", current_page=0):
"""Ajouter des reperes de coupe sur les pages."""
apply_to="all", current_page=0, **_kwargs):
"""Ajouter des reperes de coupe sur les pages.
Les marques sont placees a l'exterieur de la zone d'impression.
Chaque coin a 2 traits (1 horizontal + 1 vertical) formant un L.
La page est agrandie pour contenir les marques.
"""
reader = PdfReader(input_path)
writer = PdfWriter()
margin = mark_offset + mark_length
for i, page in enumerate(reader.pages):
page_num = i + 1
should_apply = False
@@ -27,46 +34,62 @@ def add_crop_marks(input_path, output_path, mark_length=14.17, mark_offset=7.09,
if should_apply:
w, h = get_page_size(page)
# Canvas agrandi pour inclure les marques
cw = w + 2 * margin
ch = h + 2 * margin
packet = io.BytesIO()
c = canvas.Canvas(packet, pagesize=(w, h))
c = canvas.Canvas(packet, pagesize=(cw, ch))
c.setLineWidth(line_width)
c.setStrokeColorRGB(*color)
# 4 coins
corners = [(0, 0), (w, 0), (0, h), (w, h)]
for cx, cy in corners:
# Traits horizontaux
if cx == 0:
c.line(cx - mark_offset - mark_length, cy, cx - mark_offset, cy)
else:
c.line(cx + mark_offset, cy, cx + mark_offset + mark_length, cy)
# Traits verticaux
if cy == 0:
c.line(cx, cy - mark_offset - mark_length, cx, cy - mark_offset)
else:
c.line(cx, cy + mark_offset, cx, cy + mark_offset + mark_length)
# Les coordonnees de la zone d'impression dans le canvas agrandi
ox, oy = margin, margin # origine de la page originale
# 4 coins — 2 traits par coin (L exterieur)
# Bas-gauche
c.line(ox - mark_offset - mark_length, oy, ox - mark_offset, oy)
c.line(ox, oy - mark_offset - mark_length, ox, oy - mark_offset)
# Bas-droite
c.line(ox + w + mark_offset, oy, ox + w + mark_offset + mark_length, oy)
c.line(ox + w, oy - mark_offset - mark_length, ox + w, oy - mark_offset)
# Haut-gauche
c.line(ox - mark_offset - mark_length, oy + h, ox - mark_offset, oy + h)
c.line(ox, oy + h + mark_offset, ox, oy + h + mark_offset + mark_length)
# Haut-droite
c.line(ox + w + mark_offset, oy + h, ox + w + mark_offset + mark_length, oy + h)
c.line(ox + w, oy + h + mark_offset, ox + w, oy + h + mark_offset + mark_length)
# Reperes de centrage
if center_marks:
mid_x = w / 2
mid_y = h / 2
mid_x = ox + w / 2
mid_y = oy + h / 2
ml = mark_length * 0.7
# Haut
c.line(mid_x, h + mark_offset, mid_x, h + mark_offset + ml)
c.line(mid_x, oy + h + mark_offset, mid_x, oy + h + mark_offset + ml)
# Bas
c.line(mid_x, -mark_offset, mid_x, -mark_offset - ml)
c.line(mid_x, oy - mark_offset, mid_x, oy - mark_offset - ml)
# Gauche
c.line(-mark_offset, mid_y, -mark_offset - ml, mid_y)
c.line(ox - mark_offset, mid_y, ox - mark_offset - ml, mid_y)
# Droite
c.line(w + mark_offset, mid_y, w + mark_offset + ml, mid_y)
c.line(ox + w + mark_offset, mid_y, ox + w + mark_offset + ml, mid_y)
c.showPage()
c.save()
packet.seek(0)
overlay = PdfReader(packet)
page.merge_page(overlay.pages[0])
overlay_reader = PdfReader(packet)
overlay_page = overlay_reader.pages[0]
writer.add_page(page)
# Creer une nouvelle page agrandie
new_page = PageObject.create_blank_page(width=cw, height=ch)
# Placer la page originale au centre (decalee de margin)
page.add_transformation(Transformation().translate(margin, margin))
new_page.merge_page(page)
# Ajouter les marques de coupe par-dessus
new_page.merge_page(overlay_page)
writer.add_page(new_page)
else:
writer.add_page(page)
with open(output_path, "wb") as f:
writer.write(f)