Mettez un roman japonais sur la page et la première chose que vous remarquez est que le texte descend le long de la colonne, et non le long de la ligne, et que les colonnes avancent du bord droit de la feuille vers la gauche. Un lecteur qui a grandi avec cela trouve le texte horizontal légèrement clinique. Le problème d'ingénierie est que le format PDF, comme presque tous les systèmes de texte numérique, a été construit autour d'une ligne de base (baseline) horizontale qui croît de gauche à droite, et un flux de contenu (content stream) n'a aucune notion de "écrire ce paragraphe vers le bas à la place". Ainsi, lorsqu'une application Delphi doit produire un certificat, un poème, un panneau de signalisation ou un document juridique de format traditionnel pour un lecteur taïwanais, japonais ou coréen, la mise en page doit être assemblée à la main : un caractère en dessous du suivant, une colonne à gauche de la précédente
HotPDF vous offre un commutateur (switch) qui fait la comptabilité (bookkeeping) caractère par caractère pour vous. La police que vous définissez porte un drapeau (flag) IsVertical, et une fois qu'il est activé, un seul appel TextOut empile une chaîne entière dans une colonne verticale au lieu de l'exécuter le long d'une ligne de base. Le placement de la colonne, l'ordre de droite à gauche et une substitution de glyphe discrètement importante sont ce que le reste de cette page aborde

Le commutateur réside sur SetFont
La mise en page verticale n'est pas une propriété de la page ou du document. C'est une propriété de la police avec laquelle vous dessinez, et vous l'activez avec le cinquième argument de SetFont :
// SetFont(FontName, FontStyle, Size, FontCharset, IsVertical)
// The 5th argument flips the current font into vertical mode.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, False); // horizontal
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, DEFAULT_CHARSET, True); // vertical
Parce que le drapeau dépend de la police, vous passez de l'écriture horizontale à l'écriture verticale simplement en appelant à nouveau SetFont avec un dernier argument différent. Une page peut contenir un titre horizontal en haut et un corps de texte vertical en dessous, et HotPDF sépare les deux modes par objet de police plutôt que par page. C'est ce qui rend les mises en page mixtes possibles sans aucune gestion de mode spéciale de votre part : chaque TextOut après un SetFont vertical s'empile, chaque TextOut après un SetFont horizontal court le long de la ligne de base, et le dernier SetFont l'emporte
Le quatrième argument est le jeu de caractères Windows, le même que celui d'un appel horizontal. Passer DEFAULT_CHARSET permet au système de résoudre les glyphes par chaîne, ce qui est important ici car un document vertical mélange souvent les écritures. Tout le reste concernant la police s'applique toujours : elle doit être installée sur la machine de compilation, et vous voulez presque toujours FontEmbedding := True pour que le fichier rende les mêmes glyphes CJK (chinois, japonais, coréen) sur une visionneuse qui n'a jamais eu Arial Unicode MS
Un appel TextOut est une colonne
Avec une police verticale active, un appel TextOut ne déploie plus sa chaîne latéralement à partir du point donné. Il plante le premier caractère en haut et fait descendre le reste tout droit, en avançant de la hauteur de ligne de la police pour chaque glyphe. Le X que vous passez fixe la colonne ; le Y que vous passez fixe l'endroit où le haut de la colonne commence. Pour mettre en page un vrai passage, vous émettez donc un TextOut par colonne et décalez X vers la gauche entre les appels, car les colonnes CJK se lisent de droite à gauche
var
Pdf: THotPDF;
const
ColTop = 760; // y of the first glyph in every column (points)
ColGap = 28; // horizontal distance between columns
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'VerticalText.pdf';
Pdf.FontEmbedding := True; // embed the CJK face for portable rendering
Pdf.BeginDoc;
Pdf.CurrentPage.Size := psA4;
// A horizontal heading first, in the ordinary writing mode.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 16, DEFAULT_CHARSET, False);
Pdf.CurrentPage.TextOut(60, 800, 0, 'Tang poem, vertical layout');
// Switch the font into vertical mode; every TextOut below now stacks.
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 18, DEFAULT_CHARSET, True);
// Columns advance right to left, so X decreases with each call.
Pdf.CurrentPage.TextOut(520, ColTop, 0, '床前明月光');
Pdf.CurrentPage.TextOut(520 - ColGap, ColTop, 0, '疑是地上霜');
Pdf.CurrentPage.TextOut(520 - ColGap * 2, ColTop, 0, '舉頭望明月');
Pdf.CurrentPage.TextOut(520 - ColGap * 3, ColTop, 0, '低頭思故鄉');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Le poème se lit comme il se doit : la colonne la plus à droite en premier, de haut en bas, puis l'œil saute à gauche vers la colonne suivante. Rien dans la chaîne elle-même n'encode cet ordre. Vous l'encodez dans les coordonnées X, en les diminuant appel par appel. Prenez la direction à l'envers et le verset ressortira inversé, ce qui est l'erreur la plus courante lors du portage d'une mise en page horizontale vers la verticale
Coordonnées : en bas de la page, de droite à gauche
Deux axes sont en jeu et ils tirent dans des directions opposées, il vaut donc la peine d'être précis. HotPDF mesure à partir du coin inférieur gauche de la page, avec Y augmentant vers le haut, en points. Une colonne verticale commence donc à un Y élevé (près du haut de la feuille) et les caractères descendent à partir de là à mesure que HotPDF soustrait une hauteur de ligne pour chacun d'eux. Vous définissez ce Y de départ une fois par colonne et le composant gère la descente
L'axe horizontal est celui que vous pilotez manuellement. Chaque colonne se trouve à son propre X, et les colonnes successives passent à des valeurs X plus petites car l'ordre de lecture est de droite à gauche. Un rythme judicieux consiste à choisir le X de la colonne la plus à droite, puis à soustraire un espace de colonne (column gap) fixe pour chaque appel ultérieur, comme le fait l'exemple avec ColGap. L'écart est à votre choix ; trop serré et les colonnes adjacentes se touchent, trop lâche et le bloc semble clairsemé. Pour le corps du texte de 12 à 18 points, un espace légèrement supérieur à la taille de la police se lit confortablement
Glyphes qui doivent changer de forme
Quelques caractères ne sont pas simplement des copies tournées de leurs homologues horizontaux ; ils doivent être substitués lorsque le texte devient vertical. Celui dont HotPDF s'occupe pour vous est la marque de son prolongé japonaise ー (U+30FC), la barre de voyelle longue qui apparaît dans les mots en katakana comme コーヒー. Dessiné horizontalement, c'est un tiret court sur la ligne de base. Si vous empiliez ce même glyphe dans une colonne, il serait à plat à travers la colonne, ce qui est faux : en japonais vertical, la marque devient un trait vertical reliant les deux caractères entre lesquels elle se trouve. HotPDF détecte U+30FC dans le chemin vertical et le rend comme une barre verticale (U+007C) de sorte que la marque de voyelle longue pointe dans la bonne direction sans aucun travail de votre part
Cette substitution unique couvre le cas qui brise les implémentations les plus naïves, mais il vaut la peine de savoir où le problème général va plus loin. La typographie verticale complète fait également pivoter les lettres latines et la ponctuation occidentale de quatre-vingt-dix degrés, décale les petits kanas et repositionne les crochets et les virgules sur leurs formes verticales, et une implémentation complète de cela vit dans les fonctionnalités verticales OpenType d'une police plutôt que dans des règles fixes. HotPDF peut exploiter ces fonctionnalités lorsque la police les possède : les alternatives verticales (les fonctionnalités GSUB vert et vrt2) et le crénage (kerning) vertical (les recherches GPOS vkrn et vpal) sont facultatifs (opt-in), appliqués le long du chemin vertical uniquement lorsque la police active les définit réellement. Pour le texte mixte CJK dans une seule police à large couverture comme Arial Unicode MS, la gestion U+30FC intégrée plus un pas de hauteur de ligne uniforme suffisent pour produire des colonnes correctes et lisibles ; les fonctionnalités OpenType sont importantes lorsque vous passez à une police conçue pour un réglage vertical fin et que vous souhaitez son positionnement kana natif et son espacement inter-glyphes
Mélanger les écritures et les orientations sur une page
Les vrais documents sont rarement purs. Une page japonaise verticale peut comporter une légende en anglais horizontal, un numéro de page en bas, ou un bloc de coréen défini verticalement à côté du japonais. Le drapeau vertical étant un commutateur au niveau de la police, vous les composez en alternant les appels SetFont plutôt qu'en gérant un état à l'échelle de la page. Définissez une police horizontale, écrivez l'en-tête courant (running header) et le folio, définissez une police verticale, disposez les colonnes, définissez à nouveau une police horizontale pour un pied de page (footer). Chaque région reprend le mode du SetFont le plus récent, la seule discipline requise est donc de l'appeler chaque fois que vous changez de direction
Un détail à prévoir lorsque les écritures se mélangent : les idéogrammes chinois, japonais et coréens sont presque carrés et s'empilent sur un pas régulier (even step), mais les séquences latines intégrées dans une colonne verticale n'ont pas cette avance uniforme. Si vous avez besoin de quelques mots latins dans un texte par ailleurs vertical, décidez délibérément s'ils doivent être pivotés pour descendre dans la colonne ou placés verticalement sous la forme d'un court encart horizontal, et positionnez ce fragment avec son propre TextOut plutôt que de le laisser suivre le pas vertical destiné aux idéogrammes. Traiter la séquence mixte comme son propre problème de placement permet de garder le rythme de la colonne intact
De l'exemple à la production
Les éléments sont petits et se composent de manière prévisible. Activez le drapeau vertical dans SetFont, émettez un TextOut par colonne à partir d'un Y supérieur fixe, et diminuez X d'un appel à l'autre pour que les colonnes se lisent de droite à gauche. Intégrez la police pour que les glyphes CJK survivent au voyage jusqu'à la machine du lecteur, et laissez le composant gérer la marque de voyelle longue U+30FC et, là où la police les prend en charge, les fonctionnalités verticales OpenType. À partir de là, la mise en production de la mise en page relève principalement de l'arithmétique : dériver les positions X des colonnes à partir d'une largeur de bloc mesurée, diviser les longs passages en colonnes qui s'adaptent à la hauteur de la page et réserver de l'espace pour les en-têtes et les folios horizontaux
Pour la surface de texte et de police plus large sur laquelle cela s'appuie, y compris les conventions horizontales de TextOut et l'enregistrement de police Unicode, consultez l'exemple multilingue Hello World et l'exemple TextOut. Le commutateur vertical SetFont et les appels TextOut présentés ici font partie du Composant HotPDF pour Delphi et C++Builder