Chaque chaîne visible dans la documentation de HotPDF passe par un appel : TextOut(X, Y, angle, Text). L'exemple Hello World l'utilise dans sa forme la plus simple, la police étant configurée une fois et les quatre paramètres conservant des valeurs par défaut raisonnables. Après la première page, ces mêmes quatre paramètres portent tout le poids de la mise en page. Le troisième paramètre fait pivoter la ligne de texte. La configuration de la police qui le précède détermine la taille et le style. Les coordonnées X, Y, mesurées en points depuis le coin de la page, sont le seul rempart contre les chevauchements de texte, les troncatures ou le décalage d'une ligne vers le bas sur l'imprimante de quelqu'un d'autre. C'est là que TextOut entre en jeu, et où les valeurs par défaut ne suffisent plus
La première chose d'importance à retenir concerne la signature : X et Y sont des Singles mesurés en points, angle est un Extended mesuré en degrés, et Text est un WideString, ce qui permet de transmettre de l'Unicode sans appel supplémentaire. La seconde surcharge accepte un PWORD avec une longueur, utile si vous détenez déjà les codes de glyphes, mais pour les chaînes ordinaires, la forme WideString est celle que vous choisirez
La taille et le style proviennent de SetFont et non de TextOut
TextOut fait exactement ce que vous lui dites. Il dessine les points de code dans l'ordre où vous les transmettez, de gauche à droite, ce qui est correct pour le latin, le cyrillique et le CJK, mais erroné pour l'arabe et l'hébreu. RtLTextOut est l'appel qui réorganise d'abord la ligne dans l'ordre visuel de droite à gauche avant de dessiner. HotPDF sépare délibérément ces deux méthodes au lieu de deviner la direction à partir des caractères, donc le choix de l'appel détermine le comportement d'écriture obtenu. Les mécanismes plus profonds du réordonnancement bidirectionnel et des ligatures contextuelles arabes font l'objet d'un autre sujet, présenté dans l'article Gestion de l'arabe et de la mise en forme du texte RTL avec HotPDF ; le point pratique ici est plus restreint. Utilisez RtLTextOut pour les segments de texte de droite à gauche, TextOut pour tout le reste, et n'utilisez jamais l'un pour faire le travail de l'autre
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24pt regular
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12pt bold
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11pt italic
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // styles combine
Le deuxième paramètre est un ensemble de TFontStyles, ainsi [fsBold, fsItalic] correspond à du gras italique, et [] à du style normal. La taille est exprimée en points, la même unité que les coordonnées, ce qui rend l'espacement vertical facile à raisonner : une ligne de 12 points nécessite un pas vertical d'environ 14 à 16 points pour respirer, ainsi réduire Y de 14 à chaque ligne est un point de départ raisonnable. Il n'y a pas de retour automatique à la ligne. Vous devez calculer vous-même chaque ligne de base, ce qui est fastidieux pour des paragraphes mais très précis pour des formulaires où chaque champ est positionné à des coordonnées fixes
Il y a deux remarques pratiques concernant le nom de la police. Il est résolu en fonction des polices installées sur la machine de construction, et ce que le système d'exploitation renvoie est intégré, de sorte que le nom résolu sur votre bureau et celui résolu sur le serveur de construction ne garantissent pas la même police. De plus, la police doit couvrir les scripts de la chaîne de caractères. Le rendu de texte cyrillique ou CJK sous une police uniquement latine produira des carrés de glyphes manquants sans aucune erreur, c'est pourquoi la page Hello World utilise une police Unicode à large couverture pour les langues mixtes
Le paramètre d'angle pivote autour du point d'ancrage
Le troisième paramètre est celui que la plupart des codes laissent indéfiniment à zéro. Passez une valeur non nulle pour faire pivoter la ligne de texte de ce nombre de degrés dans le sens inverse des aiguilles d'une montre autour de son point d'ancrage (X, Y), l'ancre étant le coin inférieur gauche du texte. L'ancre elle-même ne se déplace pas, de sorte que les mêmes coordonnées qui positionnent une étiquette horizontale placent également son jumeau incliné ; seule la direction de progression des glyphes change
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// A vertical axis label down the left margin: 90 degrees reads bottom-to-top.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// A diagonal DRAFT watermark across the page body.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Column headers tilted 60 degrees so long labels fit a narrow table.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
90 degrés est un cas courant, par exemple une étiquette qui s'étend vers le haut le long du côté d'un graphique ou le titre d'une reliure. 45 degrés gère les titres de colonnes inclinés, une technique qui permet de placer de longues étiquettes au-dessus de colonnes étroites sans déborder sur les colonnes voisines. La rotation ne modifie pas la façon dont le point d'ancrage est interprété, ce qui peut être déroutant : une ligne de texte à 90 degrés commence toujours à partir de (X, Y) et croît vers le haut, donc pour centrer une étiquette pivotée, vous devez ajuster l'ancrage plutôt que l'angle. Lorsque plusieurs lignes de texte pivotées partagent une ligne de base, attribuez-leur le même Y et incrémentez X, tout comme vous incrémenteriez Y pour des lignes horizontales empilées
Positionnement précis des coordonnées plutôt que des suppositions
Les coordonnées sont des points, et les points peuvent être décimaux. MoveTo et LineTo acceptent des valeurs Single, de sorte qu'une ligne fine de 0,5 point ou une position de 72,25 est valide et significative, sans être arrondie à l'entier le plus proche. Cette précision est importante dans deux directions opposées. Une épaisseur de ligne inférieure à environ 0,5 peut s'afficher comme la ligne la plus fine dépendante de l'appareil, disparaissant à l'écran pour réapparaître à l'impression, de sorte que les lignes horizontales visibles nécessitent une épaisseur définie intentionnellement par vos soins, plutôt que la valeur par défaut. D'autre part, aligner les lignes de tableau et de grille sur des coordonnées entières empêche les lignes adjacentes de sembler légèrement inégales en raison des différences d'arrondi. Déterminez l'espacement de la grille en points dès le départ, et le reste de la mise en page en héritera
Considérez la mise en page comme une arithmétique par rapport à des ancres nommées, plutôt que comme une série de nombres magiques. Une marge gauche, une ligne de base décroissante à chaque ligne et un espacement de ligne fixe peuvent transformer un bloc de valeurs littérales en une courte boucle :
const
LeftMargin = 72; // 1 inch in
TopBaseline = 720; // first line, ~1 inch down on Letter
Leading = 16; // vertical step between lines
var
Y: Single;
Line: string;
begin
Pdf.CurrentPage.SetFont('Arial', [], 11);
Y := TopBaseline;
for Line in ReportLines do
begin
Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
Y := Y - Leading;
if Y < 72 then // bottom margin reached
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // font resets on a new page
Y := TopBaseline;
end;
end;
end;
La protection de la pagination est la ligne que tout le monde oublie en premier et qui frappe le plus fort en pratique. Il n'y a pas de mise en page fluide sous TextOut. Si vous continuez à décrémenter au-delà de la marge inférieure, le texte continuera à s'écrire dans la gouttière, hors de la page, dans le vide, sans aucun avertissement. Surveillez donc vous-même le Y, appelez lorsque vous franchissez le bas, et réinitialisez la ligne de base. Le AddPageSetFont qui suit AddPage n'est pas une option : la police actuelle n'est pas conservée après un changement de page ; si vous l'omettez, la première ligne de texte de la nouvelle page apparaîtra avec la police par défaut du visualiseur
Espacement des caractères et des mots pour l'ajustement et l'alignement
Parfois, la chaîne est correcte mais la largeur est erronée : un titre devant croiser des lignes fixes, un code devant s'afficher avec des chiffres plus espacés, ou des valeurs de colonnes nécessitant un alignement précis. Le PDF intègre deux opérateurs d'état de texte à cet effet : l'espacement des caractères (Tc, espace supplémentaire ajouté après chaque glyphe) et l'espacement des mots (Tw, espace supplémentaire ajouté à chaque caractère espace), tous deux exprimés en unités d'espace de texte non mises à l'échelle, ce qui correspond en pratique à des points à la taille de police actuelle. Ce sont des états et non des paramètres de TextOut, vous les configurez, dessinez, puis les réinitialisez
// Letter-space a short heading so it stretches across a rule.
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0); // reset before normal body text
// Open up the gaps between words on a single wide line.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
L'espacement des mots ne s'applique qu'au caractère d'espace (code 32), ce qui a une conséquence d'intérêt : cela ne fonctionne pas dans les textes CJK dépourvus d'espaces ASCII, et interagit curieusement avec le texte codé en index de glyphes plutôt qu'en octets. Pour les tableaux latins, c'est un moyen économique d'élargir les écarts sans ressaisir la chaîne. L'espacement des caractères est un meilleur outil pour adapter les titres à la largeur cible car il répartit l'ajustement uniformément sur chaque glyphe, au lieu de le concentrer sur l'espace
La réinitialisation est toute la discipline. L'espacement, au même titre que la police, fait partie de l'état graphique de la page, et cet état persiste jusqu'à ce que vous le modifiiez. Configurer l'espacement des lettres sur un titre puis oublier de le remettre à zéro appliquera ce décalage à tous les paragraphes suivants, ce qui créera une sensation d'étrangeté subtile et difficile à cerner, capable de passer une relecture rapide mais capturée lors d'une relecture attentive. Une habitude fiable consiste à configurer l'espacement, tracer le texte qui le requiert, puis le réinitialiser à zéro sur la ligne suivante, de sorte que le code ultérieur n'ait pas à se soucier des actions précédentes
Vérifier la sortie là où les problèmes surviennent réellement
La mise en page du texte échoue sur la deuxième machine, et non sur la première, de sorte que les vérifications réellement importantes se font en dehors de votre bureau. Ouvrez le fichier généré sur un système où l'ensemble des polices de développement n'est pas installé, confirmez que les polices intégrées s'affichent toujours, y compris les caractères latins accentués, les écritures non latines et la ponctuation, en effectuant un passage complet plutôt qu'en vérifiant uniquement les caractères faciles. Sélectionnez et copiez quelques lignes, confirmez que le texte est du texte réel et non des contours, ce qui est crucial pour la recherche ou l'extraction. Saisissez des données représentatives (les étiquettes allemandes les plus longues et les nombres les plus larges, plutôt que des espaces réservés propres) dans la mise en page, car le texte qui déborde du champ est toujours celui que vous n'avez pas saisi manuellement. Si la page doit correspondre à un formulaire pré-imprimé, imprimez ou rasterisez un échantillon et alignez-le sur l'original ; un décalage de ligne de base d'un quart de millimètre est invisible à l'écran mais évident sur le papier
Si vous n'avez pas encore écrit de page, commencez par l'exemple Hello World de HotPDF, qui configure le document, la police et le système de coordonnées en bas à gauche dont tout dépend. Les appels TextOut, SetFont et d'espacement présentés ici font partie du composant HotPDF pour Delphi et C++Builder