Ét.Nadji.fr/

Du code, des mots, des livres.

PyScribus, une librairie Python pour Scribus

Most proprietary DTP programs store data in binary file formats that can’t be read by most human beings. […]
Scribus uses a radically different approach, because its file format is based on XML, i.e. it can be read and analyzed by using a simple text editor. This not only means that you can repair damaged files rather easily ; you can even create your own Scribus files without access to Scribus !
Site web de Scribus

Dans les métiers de l’édition, qui dit PAO dit le logiciel privateur Adobe® InDesign™. L’été dernier, à l’occasion de sa nouvelle version stable, je me suis cependant intéressé un peu plus à Scribus, un logiciel libre avec lequel, pour l’anecdote inutile, j’avais fait de la PAO pour la première fois1 et sans le savoir (après quoi j’ai découvert LATEX).

Comme je codais Frakaso, un utilitaire pour la diffusion en direct / stream, j’ai remis mon envie de contribuer à un autre logiciel libre à plus tard puisque mes compétences en matière de programmation C sont très limitées ; quant au cadriciel Qt, je le connais un peu mais surtout une de ses liaisons python, PyQt.

Revenu de congés, je ne voyais plus trop de choses à améliorer dans Frakaso : il convenait à mon usage personnel2 et essayant de coder un truc utile pour un peu plus de monde, j’ai finalement passé quelque temps à coder ce qui est le sujet de ce billet, PyScribus.

«  Oui, j’ai de drôles de loisirs. Que voulez-vous…
Par ailleurs, je dois vraiment remercier Johanna Neplaz !  »

Sommaire

  1. Principe
  2. Évolution
    1. Ce qui est actuellement visé
    2. Ce que peut faire PyScribus en l’état
    3. Quelques exemples
    4. Ce que j’aimerais que PyScribus parvienne à faire
  3. Mes difficultés
    1. Les maths
      1. Les unités de mesure
      2. Les formes des objets
    2. Lier et chasser correctement du texte
  4. Des rappels pour la fin

Principe 🔗

PyScribus permet de manipuler du SLA, c’est-à-dire le format de fichier de Scribus, basé sur XML – (pour les indesigneux : comme l’IDML, mais comme fichier principal). C’est un argument technique en sa faveur : le format de base est ouvert, et avec un peu de documentation et quelques déductions, on peut aisément comprendre ce que fait tel élément XML, comment les cadres se lient entre eux, etc.

Malheureusement, le format SLA pourrait être plus clairement documenté (il y a une DTD, néanmoins), tout n’y est pas uniforme3, l’unité de base (notamment pour les coordonnées et les longueurs) est le point pica, la façon de gérer les notes de bas de page est un peu étrange

Capture d’écran de l’élément XML /SCRIBUSUTF8NEW/DOCUMENT
Un fichier SLA édité via Vim : un des éléments XML ayant le plus d’attributs (certains sont en allemand).

Python étant le langage d’extension de Scribus, il est possible de lancer des scripts à l’intérieur de Scribus, c’est un autre de ses points forts. Il est même possible d’exécuter un script Python sans que Scribus s’affiche en le lançant en headless, mais cela nécessite tout de même d’avoir Scribus installé – or ce n’est pas forcément une dépendance souhaitable. Je n’ai pas trouvé de librairie Python manipulant du SLA sans Scribus, alors j’en code actuellement une, PyScribus.

«  Pourquoi PyScribus, et non python-sla, ou quelque nom du même genre ? Parce des librairies avec l’acronyme SLA existent déjà et qu’elles n’ont rien à voir.  »

PyScribus vise donc à :

  1. Créer, manipuler au mieux du SLA. C’est-à-dire simplifier la tâche à toutes les applications en Python qui voudraient supporter le SLA, à tous ceux qui veulent faire de la PAO libre.
  2. Permettre la documentation exhaustive et humainement lisible de ce format, en repérant les éléments et attributs XML inconnus, en reliant tel changement dans la GUI4 de Scribus à tel changement dans le SLA. Une simple DTD, de simples tableaux d’éléments et d’attributs XML ne suffisent pas.

Oh, et évidemment, c’est du logiciel libre.

Évolution 🔗

Ce qui est actuellement visé 🔗

La compréhension totale du format par ma petite personne.
C’est évidemment nécessaire pour coder PyScribus, mais aussi pour produire une série d’articles sur le format SLA, dont l’approche serait de juxtaposer le code XML et des vraies phrases à destination d’êtres humains.
L’import / export de fichiers SLA sans perte de données.
C’est déjà un défi en soi, puisqu’il faut déconstruire la structure XML et la reconstruire sans problèmes. Cela sous-entend aussi que PyScribus est capable de créer un fichier SLA vide qui ne fait pas planter Scribus.
Un cadre de manipulation du format qui ne se limite pas à un simple arbre d’éléments XML.
S’il s’agissait simplement d’obtenir un arbre XML, la librairie logicielle LXML le permet déjà. Mais vous devez déjà bien connaître le format pour savoir quoi chercher / modifier. La transformation de cet arbre en ensemble d’objets avec des méthodes et des attributs cohérents est d’une autre ampleur.
Avoir du code bien documenté
Plus facile à dire qu’à faire. En pratique, employer Sphinx, écrire de bonnes docstrings en reStructuredText.
Me former à la distribution de logiciels et de librairies faites avec Python
D’où la présence de PyScribus sur PyPI. J’apprivoise aussi (et mieux) les paquets Debian mais c’est pas pour tout de suite.

Ce que peut faire PyScribus en l’état 🔗

PyScribus peut actuellement faire suffisamment pour me permettre d’aller poser des questions à la communauté de Scribus, je ne voulais pas ramener ma poire sans avoir codé quoi que ce soit.

Enregistrer et lire partiellement un fichier SLA
Certains éléments ne sont pas encore lus / enregistrés, du fait du nombre de choses à traiter et d’une complexité variable des fichiers selon le type de documents. Les objets avec des formes complexes (non rectangulaires) sautent pour le moment.
Ajouter du contenu
Il est possible d’ajouter des objets, des styles, du texte mais pas des pages.
Créer un schéma en fil de fer d’un document
Bien pratique pour vérifier l’aspect général d’un fichier sans Scribus. On utilise le successeur de la PIL pour ça.
 
Fichier source et fil de fer généré par le module wireframe de PyScribus 

Quelques exemples 🔗

Ce que j’aimerais que PyScribus parvienne à faire à long terme 🔗

Mes difficultés 🔗

Les maths 🔗

Dans la mesure où on manipule essentiellement des objets dont la forme est rectangulaire, il y a peu de mathématiques à faire, et encore moins de maths compliquées (pour le littéraire que je suis). Mais il y a quelques petites choses à noter.

Les unités de mesure 🔗

J’en ai déjà un peu parlé, l’unité de mesure la plus employée dans Scribus est le point pica, un choix qui est judicieux, mais un peu déstabilisant quand on « pense » en système métrique.

Scribus doit convenir aussi bien à des utilisateurs du système métrique qu’à des utilisateurs des unités anglo-saxonnes, et l’expérience a montré que traiter des données dans deux systèmes de mesure est une fichue mauvaise idée. C’est donc un choix d’unité qui embête tout le monde sauf les utilisateurs qui voudraient vraiment travailler avec des points (après tout, c’est une unité typographique connue).

Il faut également prendre en compte des pourcentages exprimées de deux façons (en fraction ou en décimal), des degrés (avec un cas spécifique), des points et des lignes par pouce

Tout cela nécessite de créer des abstractions pour les unités, que ce soit pour PyScribus ou pour ceux qui utilisent PyScribus, et de veiller maniaquement à ce que l’export de valeurs se fasse dans la bonne unité.

Les formes des objets 🔗

Tout objet sur une page de Scribus s’inscrit dans un rectangle, mais sa forme n’occupe pas forcément le rectangle entier. En plus des coordonnées, de la largeur, de la hauteur, du degré de rotation, Scribus doit donc encoder cette forme, avec un système de points avec des coordonnées relatives à l’objet.

Ainsi, si Scribus lit la définition d’un cadre de texte dont il connait les coordonnées, etc, mais non sa forme, le cadre apparaît, mais rien ne s’y affiche et on ne peut pas utiliser l’éditeur de forme.

Mise à jour (juin 2020)

Eurêka bon sang. C’est des chemins SVG. C’est une bonne chose, on s’appuie sur une norme existante, mais encore faut-il le savoir…
Nom de nom, que c’est jouissif que de comprendre de nouvelles choses !

Or la manière d’encoder les points est loin d’être évidente. Par exemple, ce qui suit est la définition d’une forme rectangulaire, avec 4 points5 :

M0 0 L515.276 0 L515.276 761.89 L0 761.89 L0 0 Z

Ce que signifie M0 0 et Z, je ne sais pas encore. M0 0 définit le point de départ, L indique une droite (pas Bézier), Z clôt le chemin.

Après ce segment, les points sont listés dans le sens horaire, en partant du premier point dont l’abscisse n’est pas nulle. Le dernier point listé est l’origine, L0 0.

Ce fonctionnement a été déduit en examinant le code et les coordonnées de chaque point dans l’interface de Scribus. Mais ce n’est pas la même affaire pour des courbes de Bézier.

Lier et chasser correctement du texte 🔗

La façon dont est encodée les cadres de texte liés dans le SLA est à peu près identifiée, mais elle pose quelques difficultés pour l’implémenter facilement et dans le bon ordre.

De plus, comment parvenir à créer autant de cadres de texte qu’il est nécessaire quand il existe du texte en excès ? Dans les fichiers SLA, le code du premier cadre de texte concentre tous le contenu, et les cadres liés font référence au cadre précédent ; il n’y a pas de marqueur de passage d’un cadre à un autre.

Je suppose que Scribus parvient à déterminer le nombre de lignes visibles en répertoriant les corps des styles de texte appliqués et en le comparant aux dimensions du cadre de texte, notées en aussi en point… Et cela, alors même que le stylage peut être direct (comme dans un traitement de texte mal utilisé), indirect (styles définis), voire direct et indirect (variation ponctuelle d’un style défini).

De sorte que pour créer une fonction renvoyant le cadre correspondant à une recherche plein-texte, il faudrait d’abord faire ces calculs avant de déterminer effectivement quel cadre renvoyer…

Des rappels pour la fin 🔗

Notes

  1. Scribus devait être en 1.3, c’était une version portable sous Windows® qui ramait sévèrement, car il fallait redécouvrir les polices d’écriture à chaque lancement. Les ennuyeux trouveront que plus de dix ans pour passer d’une 1.3 à une 1.5.5, c’est long, mais on ne parle pas de tâches simples à programmer.  
  2. Il me reste encore à apprendre comment bien distribuer une telle application sur plusieurs plateformes. Il n’est pas évident de trouver la documentation appropriée et de l’appliquer… En tout cas, Frakaso fonctionne à présent sous Windows.  
  3. Les éléments XML et leurs attributs ne sont pas très constants dans leur casse (en toutes caps, en casse chameau, etc) voire dans leur langue (il reste quelques attributs en allemand). Mais peut-on vraiment se permettre de faire une version qui casserait la compatibilité ? Quand on voit comment s’est passé la transition de Python 2 à Python 3…  
  4. Certaines préférences de l’interface graphique de Scribus sont en effet encodées dans le SLA. Le magnétisme des objets, certaines couleurs par exemple.  
  5. Oui, ça a l’air d’une précision inutile, mais le rectangle aurait très bien pu être décrit avec uniquement deux points.  

Commentaires

Pour commenter ce billet, envoyez un mail sur etnadji (at) eml.cc, ou créez-vous votre blog.