// Imposition-02-Livret.js // --------------------------------------------------------------------------- // Suite d'imposition professionnelle - Folder-Level Script pour Adobe Acrobat Pro // Module 2 : Creer un livret / Delivretiser (signature de cahier, piqure a cheval) // // Depend de Imposition-00-Core.js (doit etre charge avant). // // ATTENTION TECHNIQUE - a lire avant utilisation en production : // Le placement des pages source sur les planches composites repose sur // CDImp.Util.placerPageDansRect()/extraireRegionPage() (voir Core.js), qui // utilisent la technique "template + recadrage de CropBox" standard en // JavaScript pur pour Acrobat (sans plugin natif). Cette technique n'a pas // pu etre executee/verifiee dans une vraie session Acrobat depuis cet // environnement de developpement (Acrobat n'y est pas installe) : a tester // sur un PDF reel avant tout usage en production. // --------------------------------------------------------------------------- if (typeof CDImp === "undefined") { throw new Error("Imposition-02-Livret.js : CDImp.Core doit etre charge avant ce fichier."); } CDImp.Livret = CDImp.Livret || {}; // ----------------------------------------------------------------------- // Calcul de l'ordre des pages (imposition en cahier unique, piqure a cheval) // ----------------------------------------------------------------------- /** * Calcule l'imbrication des pages pour un cahier unique (selle/pliage central). * Fonction symetrique : utilisee aussi bien pour imposer (Page logique -> * position sur planche) que pour delivretiser (position sur planche -> page * logique), puisque l'imposition en cahier simple est sa propre inverse au * niveau de la formule (seul le sens d'utilisation change). * * Pour N pages (multiple de 4), chaque feuille porte 4 pages : 2 au recto, * 2 au verso. Exemple pour N=8 : * Feuille 1 - recto : (8 | 1) verso : (2 | 7) * Feuille 2 - recto : (6 | 3) verso : (4 | 5) * * @param {Number} nPages nombre total de pages (doit etre un multiple de 4) * @returns {Array} liste de planches, dans l'ordre d'impression : * [{ feuille: 1, face: "recto", gauche: 8, droite: 1 }, ...] * "gauche"/"droite" sont des numeros de page 1-based du document source. */ CDImp.Livret.calculerOrdre = function (nPages) { if (nPages % 4 !== 0) { throw new Error("calculerOrdre : le nombre de pages (" + nPages + ") doit etre un multiple de 4."); } var nFeuilles = nPages / 4; var planches = []; for (var s = 0; s < nFeuilles; s++) { planches.push({ feuille: s + 1, face: "recto", gauche: nPages - 2 * s, droite: 2 * s + 1 }); planches.push({ feuille: s + 1, face: "verso", gauche: 2 * s + 2, droite: nPages - 2 * s - 1 }); } return planches; }; // ----------------------------------------------------------------------- // Ajout de pages blanches pour atteindre un multiple de 4 // ----------------------------------------------------------------------- /** * Insere nManque pages blanches dans doc, a la position demandee. * Les pages blanches reprennent le format (largeur/hauteur) de la premiere * page du document. * * @param {Doc} doc document a modifier (modification en place) * @param {Number} nManque nombre de pages blanches a ajouter * @param {String} position "debut" | "fin" | "apres_couverture" */ CDImp.Livret.ajouterPagesBlanches = function (doc, nManque, position) { if (nManque <= 0) { return; } var boxRef = doc.getPageBox({ nPage: 0, cBox: "Crop" }); var largeur = Math.abs(boxRef[2] - boxRef[0]); var hauteur = Math.abs(boxRef[3] - boxRef[1]); CDImp.Util.avecPrivileges(function () { for (var k = 0; k < nManque; k++) { var idxInsertion; switch (position) { case "debut": idxInsertion = 0; break; case "apres_couverture": idxInsertion = 1; break; case "fin": default: idxInsertion = doc.numPages; // toujours recalcule : ajoute en fin break; } doc.newPage({ nPage: idxInsertion, width: largeur, height: hauteur }); } }); }; /** * Demande a l'utilisateur ou inserer les pages blanches manquantes, via un * menu contextuel simple (app.popUpMenu, API stable et bien documentee, * preferee ici a un second execDialog pour limiter les risques sur un choix * aussi simple). * * @returns {String|null} "debut" | "fin" | "apres_couverture", ou null si * l'utilisateur annule. */ CDImp.Livret._demanderPositionPagesBlanches = function (nManque) { var choix = app.popUpMenu( { cName: "A la fin du document (" + nManque + " page(s))", cReturn: "fin" }, { cName: "Au debut du document (" + nManque + " page(s))", cReturn: "debut" }, { cName: "Juste apres la couverture (page 1)", cReturn: "apres_couverture" } ); return choix || null; }; // ----------------------------------------------------------------------- // Construction du document imposes (sens direct : pages -> livret) // ----------------------------------------------------------------------- /** * Construit le document de sortie : une page composite (format double, en * paysage) par planche recto/verso, avec les deux pages source positionnees * cote a cote. * * @param {Doc} srcDoc document source (deja complete a un multiple de 4 pages) * @param {Array} planches resultat de CDImp.Livret.calculerOrdre() * @param {Number} creepMm compensation de chasse en mm, appliquee * progressivement vers l'interieur du cahier (0 = desactive) * @returns {Doc} le nouveau document compose */ CDImp.Livret.construireDocument = function (srcDoc, planches, creepMm) { var boxSrc = srcDoc.getPageBox({ nPage: 0, cBox: "Crop" }); var largeurSrc = Math.abs(boxSrc[2] - boxSrc[0]); var hauteurSrc = Math.abs(boxSrc[3] - boxSrc[1]); var largeurDest = largeurSrc * 2; var hauteurDest = hauteurSrc; var nFeuilles = planches.length / 2; var destDoc; CDImp.Util.avecPrivileges(function () { destDoc = new Doc(); destDoc.newPage({ nPage: 0, width: largeurDest, height: hauteurDest }); for (var k = 1; k < planches.length; k++) { destDoc.newPage({ nPage: k, width: largeurDest, height: hauteurDest }); } }); for (var i = 0; i < planches.length; i++) { var planche = planches[i]; // Decalage de chasse (creep) : croissant en s'eloignant du centre du // cahier vers l'exterieur, applique symetriquement gauche/droite. var decalageCreepPt = creepMm ? CDImp.Util.mmToPt(creepMm) * (nFeuilles - planche.feuille) : 0; CDImp.Util.placerPageDansRect(srcDoc, planche.gauche, destDoc, i, [decalageCreepPt, 0, decalageCreepPt + largeurSrc, hauteurSrc]); CDImp.Util.placerPageDansRect(srcDoc, planche.droite, destDoc, i, [largeurSrc - decalageCreepPt, 0, largeurDest - decalageCreepPt, hauteurSrc]); } return destDoc; }; // ----------------------------------------------------------------------- // Delivretisation (sens inverse : livret imposes -> ordre de lecture normal) // ----------------------------------------------------------------------- /** * Reconstitue l'ordre de lecture normal d'un PDF imposé en cahier piqûre a * cheval : chaque page du document source est une planche double (recto ou * verso) contenant deux pages logiques cote a cote, dans l'ordre produit par * CDImp.Livret.construireDocument(). On reutilise calculerOrdre() pour * retrouver, pour chaque planche, les numeros de page logique a replacer a * gauche et a droite, puis on extrait chaque moitie vers sa position finale. * * Limite connue : ne compense pas une eventuelle chasse (creep) appliquee * lors de l'imposition d'origine (les pages reconstituees seront legerement * decalees si un creep non nul avait ete utilise). * * @param {Doc} doc document imposes (planches doubles), document actif si omis */ CDImp.Livret.delivretiser = function (doc) { doc = CDImp.Util.getDocActif(doc); var nPlanches = doc.numPages; if (nPlanches % 2 !== 0) { CDImp.Util.erreur("Delivretiser : le document doit contenir un nombre pair de planches\n(une planche recto + une planche verso par feuille)."); return; } var nPagesLogiques = nPlanches * 2; var planches; try { planches = CDImp.Livret.calculerOrdre(nPagesLogiques); } catch (e) { CDImp.Util.erreur(e.toString()); return; } var boxRef = doc.getPageBox({ nPage: 0, cBox: "Crop" }); var largeurPlanche = Math.abs(boxRef[2] - boxRef[0]); var hauteur = Math.abs(boxRef[3] - boxRef[1]); var largeurDemiPage = largeurPlanche / 2; var destDoc; try { CDImp.Util.avecPrivileges(function () { destDoc = new Doc(); destDoc.newPage({ nPage: 0, width: largeurDemiPage, height: hauteur }); for (var k = 1; k < nPagesLogiques; k++) { destDoc.newPage({ nPage: k, width: largeurDemiPage, height: hauteur }); } }); for (var i = 0; i < planches.length; i++) { var planche = planches[i]; var rectGauche = [0, 0, largeurDemiPage, hauteur]; var rectDroite = [largeurDemiPage, 0, largeurPlanche, hauteur]; CDImp.Util.extraireRegionPage(doc, i + 1, rectGauche, destDoc, planche.gauche - 1); CDImp.Util.extraireRegionPage(doc, i + 1, rectDroite, destDoc, planche.droite - 1); } } catch (e) { CDImp.Util.erreur("Erreur lors de la delivretisation : " + e.toString()); return; } if (CDImp.Auto && CDImp.Auto.enregistrerDerniereAction) { CDImp.Auto.enregistrerDerniereAction("Livret.delivretiser", {}); } CDImp.Util.info("Delivretisation terminee (" + nPagesLogiques + " pages reconstituees).\nPensez a l'enregistrer (Ctrl+S) sous un nouveau nom."); }; // ----------------------------------------------------------------------- // Point d'entree du module (appele depuis le panneau principal, Module 1) // ----------------------------------------------------------------------- CDImp.Livret.imposer = function () { var doc = CDImp.Util.getDocActif(); var nPages = doc.numPages; var reste = nPages % 4; var info = "Document : " + nPages + " pages."; if (reste !== 0) { info += "\n" + (4 - reste) + " page(s) blanche(s) seront ajoutees a la fin."; } var saisie = app.response({ cQuestion: info + "\n\nCompensation de chasse (creep) en mm par feuille :\n(0 = aucune)", cTitle: "Imposer un livret", cDefault: "0" }); if (saisie === null) return; var creepMm = parseFloat(saisie) || 0; if (reste !== 0) { CDImp.Livret.ajouterPagesBlanches(doc, 4 - reste, "fin"); nPages = doc.numPages; } var planches = CDImp.Livret.calculerOrdre(nPages); var destDoc = CDImp.Livret.construireDocument(doc, planches, creepMm); if (CDImp.Auto && CDImp.Auto.enregistrerDerniereAction) { CDImp.Auto.enregistrerDerniereAction("Livret.imposer", { creepMm: creepMm }); } app.alert("Livret cree avec succes (" + planches.length + " planches).\nPensez a l'enregistrer sous un nouveau nom."); CDImp.Util.info("Livret cree avec succes (" + planches.length + " planches).\nPensez a l'enregistrer (Ctrl+S) sous un nouveau nom."); }; /** * Variante directe sans dialogues, utilisee par le Module 7 (Automatisation) * pour rejouer une action enregistree sur un nouveau document. Ne gere pas * l'ajout de pages blanches (le document doit deja etre un multiple de 4). */ CDImp.Livret.executerAvecParams = function (doc, params) { doc = CDImp.Util.getDocActif(doc); var nPages = doc.numPages; if (nPages % 4 !== 0) { CDImp.Util.erreur("Repeter l'action : le document (" + nPages + " pages) n'est pas un multiple de 4.\nUtilisez le module Livret manuellement pour ajouter les pages blanches."); return; } var planches = CDImp.Livret.calculerOrdre(nPages); var destDoc = CDImp.Livret.construireDocument(doc, planches, params.creepMm || 0); CDImp.Util.info("Livret recree avec succes (" + planches.length + " planches)."); return destDoc; };