Impostate 「コード」 lungo la pagina disegnandolo un carattere alla volta, ogni chiamata un em più in basso della precedente, e tre dei cinque glifi vengono sbagliati. Le due parentesi angolari stanno nella colonna come stanno su una riga orizzontale, aprendo di lato, e il segno di vocale lunga ー è un trattino piatto che taglia attraverso la colonna dove un lettore giapponese si aspetta un breve tratto verticale. Solo コ e ド, i due katakana ordinari, sembrano come li comporrebbe un tipografo
Ruotare l'intera riga di novanta gradi sistema le parentesi e il segno di vocale lunga più o meno per accidente e rompe tutto il resto: ogni kanji e kana ora giace di lato. La scrittura verticale fa tre cose insieme. I caratteri restano dritti, l'avanzamento scende lungo la pagina invece di attraversarla, e una manciata di caratteri passa a disegni diversi. Centrare tutte e tre richiede un font che porti forme verticali e metriche verticali, e un font PDF impostato per usarle
Attivare la scrittura verticale in PDF Library for Delphi
PDF Library for Delphi tratta la scrittura verticale come una modalità di disegno. SetVerticalWritingMode(1) la accende, ogni chiamata DrawText dopo quella scende lungo la pagina dal punto che le date, e SetVerticalWritingMode(0) riporta il testo orizzontale. Il setter restituisce la modalità in vigore prima della chiamata e GetVerticalWritingMode legge quella corrente, così una routine di supporto può cambiare la modalità e rimettere poi esattamente ciò che ha trovato
Le due coordinate significano qualcosa di leggermente diverso dal testo orizzontale. Il valore x nomina la linea centrale della colonna: ogni glifo pende con la sua metà orizzontale su quella linea, così un segno di punteggiatura stretto e un kanji a larghezza piena restano allineati sullo stesso asse. Il valore y è la cima della prima cella carattere, e la colonna cresce verso il basso da lì. Con SetOrigin(1), che mette y = 0 al bordo superiore della pagina, l'aritmetica si legge come disegnereste la pagina sulla carta
var
Lib: TPDFlib;
H: Double;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1);
Lib.AddTrueTypeFont('MS Mincho', 1); // 1 = incorpora il font
Lib.SetTextSize(12);
Lib.SetVerticalWritingMode(1); // il DrawText ordinario ora scende
H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
Lib.DrawText(480, 72, '第三章 保守点検'); // la colonna parte da y = 72
Lib.SetVerticalWritingMode(0); // di nuovo orizzontale
// Origin 1 mette y = 0 in cima, quindi 72 + H è il piede della colonna;
// la didascalia orizzontale sta una riga più sotto
Lib.DrawText(456, 72 + H + 18, 'Chapter 3');
Lib.SaveToFile('manual-ja.pdf');
finally
Lib.Free;
end;
end;
GetVerticalTextHeight prende il nome del font, la dimensione e il testo, e restituisce la lunghezza della colonna in punti. Nell'esempio, 72 + H è il piede della colonna e la didascalia inglese va 18 punti più in basso, partendo 24 punti a sinistra della linea centrale della colonna così la breve riga latina sta più o meno sotto la colonna. La funzione restituisce 0 quando non riesce ad aprire un font con quel nome, e un layout costruito su altezza zero mette la didascalia sopra la colonna, quindi provatelo prima di usare il valore
Perché le parentesi stanno di lato in una colonna verticale?
Perché il font tiene due disegni di ciascun carattere di questo tipo e quello orizzontale è il predefinito. I font OpenType elencano le alternative in una feature GSUB chiamata vert, o vrt2 nei font che spediscono glifi già ruotati per la composizione verticale. Comporre una riga di testo restituisce i glifi orizzontali, e qualcosa deve applicare la feature verticale dopo, un glifo per un glifo. Parentesi angolari, tonde e il segno di vocale lunga si girano per correre lungo la colonna; i piccoli kana e la punteggiatura come 、 e 。 si spostano in un angolo diverso del loro quadrato
PDF Library for Delphi legge quella feature dal font con cui sta disegnando e scambia ogni glifo con la forma verticale che il font nomina. Quando un font porta entrambe le feature, vrt2 vince e vert viene ignorata. La specifica intende che vrt2 sostituisca vert, e leggere entrambe può consegnare a un carattere due glifi verticali diversi a seconda di quale lookup risponde prima. Un font che non ha nessuna delle due feature conserva i glifi ordinari. Preferiamo quell'esito a una tabella di sostituzione integrata: una tabella indovinata centra i caratteri comuni e scavalca in silenzio i font i cui progettisti hanno trattato un carattere diversamente
Scaricate le tabelle GSUB delle copie che spediscono con Windows e i conteggi sono molto lontani: la feature verticale di MS Gothic mappa 979 glifi, Yu Gothic 2.491, SimSun 72, e Arial nessuno affatto (i numeri esatti si muovono con le versioni dei font). Un font latino che capita di contenere qualche kana disegnerà una colonna dritta con ogni parentesi e segno di vocale lunga nella sua forma orizzontale, perché nel font non c'è nulla da sostituire
La sostituzione cambia anche la misurazione. Una forma verticale può avere il suo avanzamento, diverso dal glifo orizzontale che sostituisce, quindi GetVerticalTextHeight applica la stessa sostituzione prima di sommare gli avanzamenti. Misurate le forme orizzontali e disegnate quelle verticali e la colonna sconfinerà nel box che le avete riservato di qualche punto per parentesi
Tutto ciò non tocca il testo. Copiate la colonna da un viewer e vi torna 「コード」, perché ogni glifo verticale mappa al carattere che avete passato. Ricerca ed estrazione di testo vedono la vostra stringa sorgente, mai le forme di presentazione ruotate
Come le metriche verticali finiscono nel PDF
Ogni carattere in un tratto verticale avanza della distanza che le metriche verticali del font stesso gli danno. Aprite l'output in un ispettore PDF e troverete un font Type0 con codifica Identity-V il cui CIDFont porta una voce W2 per ogni glifo usato: l'avanzamento verticale dalla tabella vmtx del font, metà della larghezza del glifo come offset verso la linea centrale della colonna, e l'origine verticale. ISO 32000-1 §9.7.4.3 definisce quei tre numeri. Per un font senza metriche verticali non c'è array W2, e il predefinito DW2 fa avanzare ogni carattere di esattamente un em
L'origine verticale è dove i font di terze parti sono in disaccordo tra loro. La tabella vhea ha campi ascender e descender che sembrano la fonte ovvia, ma la convenzione del segno del descender non è condivisa tra i font. Leggete il campo dalle copie di Windows con qualunque visualizzatore di tabelle font e viene fuori +140 in MS Gothic e +120 in Yu Gothic, contro −144 in SimSun e −500 in MingLiU, e i valori possono cambiare con le versioni dei font. Qualsiasi posizione derivata da quel campo deriva di un ammontare diverso per ogni font. PDF Library for Delphi prende l'origine dall'ascender verticale, che i font CJK nominati sopra riportano in modo coerente, e ripiega su 880 unità — il predefinito che la specifica PDF stessa dà a DW2 — quando un font non riporta nulla di plausibile
Posizionare i glifi verticali a mano ha la sua trappola. Il testo orizzontale spesso fissa la spaziatura con numeri dentro un array TJ. Sotto una modalità di scrittura verticale, ISO 32000-1 §9.4.4 applica quei numeri lungo la colonna, quindi una correzione calcolata per la spaziatura orizzontale spinge ogni carattere più in giù nella pagina. Ecco perché un tratto verticale nello stream di contenuto è una semplice stringa di codici glifo senza alcuna correzione, e ogni bit di spaziatura arriva da W2
Quando controllate l'output, guardate l'inchiostro invece dei dizionari. Trovare /Identity-V nel font prova che la codifica è stata dichiarata; non dice nulla su in che direzione corre davvero il testo. Renderizzare la pagina e misurare il bounding box dei pixel disegnati lo dice: un tratto di sette caratteri dovrebbe venire fuori circa un carattere largo e sette caratteri alto
Un tratto verticale su una pagina orizzontale
DrawVerticalText disegna un singolo tratto in verticale e lascia stare la modalità di scrittura. Prende la posizione, il nome del font, la dimensione e il testo, quindi anche la selezione del font corrente resta intatta. Etichette di dorso, timbri di sigillo, una singola colonna di nomi accanto a una tabella: queste sono le eccezioni verticali dentro un documento orizzontale, e commutare una modalità globale on e off attorno a ognuna è più stato di quanto il lavoro meriti
// Un tratto verticale dentro una pagina per il resto orizzontale
if Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録') = 0 then
begin
// Il font non poteva essere aperto o non poteva comporre questo testo.
// LogLayoutProblem è una routine vostra, non parte della libreria
LogLayoutProblem('vertical label on page ' + IntToStr(Lib.SelectedPage));
end;
// Il testo orizzontale attorno non è toccato
Lib.DrawText(72, 96, 'Maintenance inspection record');
Una pagina che mescola entrambe le direzioni porta il font due volte nelle sue risorse, una con codifica orizzontale e una con Identity-V, costruiti dallo stesso programma font. Ogni direzione conserva le proprie metriche, quindi una pagina di libro giapponese con testo corrente verticale e titoli correnti orizzontali, o un certificato cinese con un titolo verticale sopra righe di dettaglio orizzontali, viene fuori con entrambe le direzioni spaziate correttamente
Il valore di ritorno è il motivo per cui ci affidiamo a DrawVerticalText anche in documenti che sono per lo più verticali. Nel disegno a modalità, un tratto che non può essere composto in verticale viene disegnato al modo orizzontale ordinario invece di essere lasciato cadere, e DrawText riporta successo in entrambi i casi. Per il testo corrente è il predefinito migliore, dato che una riga orizzontale vagante si becca facilmente in prova e un paragrafo mancante no. Per un'etichetta la cui direzione è il punto centrale, usate DrawVerticalText e trattate uno 0 come fallimento di layout
Comporre colonne da destra a sinistra
L'ordine delle colonne lo decidete voi. Il testo verticale giapponese e cinese tradizionale si legge colonna per colonna da destra a sinistra, quindi una pagina parte dal suo margine destro e ogni nuova colonna sta a sinistra della precedente. Nessuna impostazione di modalità di scrittura può dedurlo dal testo, e lo stesso vale per l'ordine delle pagine in un libro rilegato a destra e per dove appartengono furigana, note e didascalie delle figure
La routine sotto spezza una stringa in colonne che stanno in un'altezza fissa, misurando con GetVerticalTextHeight man mano e scattando a sinistra di un em e mezzo per colonna:
procedure DrawColumns(Lib: TPDFlib; const Face: WideString; Size: Double;
const Text: WideString; Right, Top, BoxH: Double);
var
Col, Trial: WideString;
I: Integer;
X: Double;
begin
// Guardia suggerita, non un controllo della libreria: un'altezza zero significa che il font
// non poteva essere aperto, e il loop sotto non spezzerebbe mai una colonna
if Lib.GetVerticalTextHeight(Face, Size, Text) <= 0 then
Exit;
X := Right; // prima colonna al margine destro
Col := '';
for I := 1 to Length(Text) do // assume nessuna coppia surrogate
begin
Trial := Col + Text[I];
if (Col <> '') and (Lib.GetVerticalTextHeight(Face, Size, Trial) > BoxH) then
begin
Lib.DrawVerticalText(X, Top, Face, Size, Col);
X := X - Size * 1.5; // colonna successiva a sinistra
Col := Text[I];
end
else
Col := Trial;
end;
if Col <> '' then
Lib.DrawVerticalText(X, Top, Face, Size, Col);
end;
Ri-misurare la stringa di prova a ogni carattere è più lento che sommare avanzamenti, ma misura esattamente ciò che sarà disegnato, sostituzioni incluse. Ciò che il loop non fa è applicare le regole kinsoku. Una parentesi chiusa o 。 in cima a una colonna, o una parentesi aperta arenata al piede di una, è un errore di composizione per un lettore giapponese, e sistemarlo significa tirare o spingere un carattere attraverso l'interruzione prima di disegnare. Le coppie surrogate vogliono la stessa cura: indicizzare Text[I] spacca a metà un carattere fuori dal Basic Multilingual Plane, quindi avanzate per code point se il vostro testo può contenerne uno
Per documenti assemblati da dati, la guida di ricerca testo ed enumerazione degli elementi di pagina mostra come rileggere ciò che è atterrato su ogni pagina, che è un modo rapido per confermare che ogni colonna porta i caratteri che intendevate
Quale font dovrebbe usare un documento verticale?
Un font CJK con metriche verticali proprie e una feature vert o vrt2. Senza di esse avete caratteri dritti che avanzano un em alla volta e nessun cambio di forma. Quando il testo verticale sembra leggermente sbagliato, esaminate il font prima di esaminare il codice. Un visualizzatore di tabelle che elenca le feature GSUB di un font e le sue tabelle vhea e vmtx vi dice in un minuto se quel font può fare il lavoro
DrawVerticalText e GetVerticalTextHeight aprono un font installato per nome attraverso Windows. Nelle build Lazarus per altre piattaforme, la scrittura verticale passa per SetVerticalWritingMode e DrawText, che lavorano dal programma del font che avete caricato e selezionato, quindi le stesse forme e metriche verticali si applicano finché quel font è il font CJK che intendevate usare
L'incorporamento segue le regole usuali e i costi usuali. Un font CJK completo arriva a molti megabyte, quindi il subsetting è il predefinito sensato per qualsiasi documento che lascia la vostra macchina. Le note su ottimizzazione della dimensione dei file PDF e subsetting dei font trattano cosa aspettarsi, e la guida di incorporare i font mancanti in un PDF esistente copre il caso di riparazione in cui un documento verticale arriva senza i suoi font
La scrittura CJK verticale sta nella stessa API di disegno del resto delle funzioni di testo in PDF Library for Delphi, una libreria PDF Pascal nativa per Delphi, C++Builder e Lazarus. La pagina del prodotto PDF Library for Delphi elenca il set completo di funzionalità font e testo accanto ad essa