Fiecare șir vizibil dintr-un document HotPDF sosește printr-un singur apel: TextOut(X, Y, angle, Text). Exemplul Hello World îl folosește în forma lui cea mai simplă, cu fontul setat o dată și cu patru argumente lăsate la valori implicite rezonabile. Dincolo de acea primă pagină, aceleași patru argumente duc toată greutatea aranjamentului. Al treilea argument rotește secvența de text. Fontul setat chiar înaintea ei hotărăște dimensiunea și stilul. Iar perechea X, Y, măsurată din colțul paginii în puncte, este singurul lucru care stă între un raport curat și un text care se suprapune, se taie sau alunecă un rând mai jos pe imprimanta altcuiva. Aici își merită TextOut locul și aici valorile implicite încetează să fie de ajuns
Merită fixată în minte semnătura, înainte de orice altceva: X și Y sunt Single în puncte, angle este un Extended în grade, iar Text este un WideString, deci Unicode trece fără vreun apel separat. O a doua supraîncărcare primește un PWORD plus o lungime, pentru cazul în care aveți deja coduri de glife, dar pentru șiruri obișnuite forma cu WideString este cea la care apelați
Dimensiunea și stilul vin din SetFont, nu din TextOut
TextOut nu are parametru de dimensiune. Dimensiunea, grosimea, înclinarea, toate stau în apelul SetFont care precedă secvența și rămân în vigoare până când următorul SetFont le înlocuiește. Acesta este faptul care explică cea mai mare parte a confuziei din prima zi: o linie iese aldină pentru că, cu trei apeluri mai devreme, ceva a setat [fsBold] și nimic nu a golit setarea
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24pt normal
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12pt aldin
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11pt cursiv
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // stilurile se combină
Al doilea argument este o mulțime TFontStyles, deci [fsBold, fsItalic] înseamnă aldin cursiv, iar [] înseamnă simplu. Dimensiunea este în puncte, aceeași unitate ca a coordonatelor, ceea ce face ușor de judecat distanțarea pe verticală: o linie de 12 puncte vrea cam 14 până la 16 puncte de pas vertical ca să respire, deci scăderea lui Y cu 14 pe linie este un interlinie de pornire rezonabil. Nu există niciun avans automat de linie. Fiecare linie de bază o calculați chiar dumneavoastră, ceea ce este obositor pentru un paragraf, dar exact pentru un formular, unde fiecare câmp stă la o coordonată fixă
Două note practice despre numele fontului. El este rezolvat față de fonturile instalate pe mașina de compilare, iar ce înapoiază sistemul de operare este ce se încorporează, deci un nume care se rezolvă pe desktopul dumneavoastră și un nume care se rezolvă pe un server de compilare nu sunt garantat același font. Iar fontul trebuie să acopere scrierile din șir. O secvență de text chirilic sau CJK cu un font doar latin se randează ca niște casete de glifă lipsă, fără nicio eroare, motiv pentru care pagina Hello World apelează la un font Unicode larg atunci când amestecă limbi
Argumentul de unghi rotește în jurul ancorei
Al treilea argument este cel pe care mai tot codul îl lasă la zero pentru totdeauna. Transmiteți o valoare diferită de zero și secvența se rotește în sens trigonometric în jurul propriei ancore (X, Y), stânga jos a textului, cu atâtea grade. Ancora în sine nu se mișcă, deci aceeași coordonată care a plasat o etichetă orizontală plasează și geamăna ei rotită; se schimbă doar direcția în care mărșăluiesc glifele
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// O etichetă de axă verticală pe marginea din stânga: 90 de grade se citește de jos în sus.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// Un filigran DRAFT diagonal peste corpul paginii.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Antete de coloană înclinate la 60 de grade, ca etichetele lungi să încapă într-un tabel îngust.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
Nouăzeci de grade este cazul obișnuit, o etichetă care urcă pe latura unui grafic sau un titlu de cotor. Patruzeci și cinci de grade rezolvă antetele de coloană înclinate, trucul care lasă o etichetă lată să stea peste o coloană îngustă fără să se reverse peste vecine. Rotația nu schimbă felul în care este interpretată ancora, ceea ce încurcă lumea: o secvență la 90 de grade tot începe la (X, Y) și crește de acolo în sus, deci, ca să centrați o etichetă rotită, ajustați ancora, nu unghiul. Când mai multe secvențe rotite împart o linie de bază, dați-le același Y și pășiți pe X, exact cum ați păși pe Y pentru linii orizontale stivuite
Plasarea coordonatelor fără să ghiciți
Coordonatele sunt partea care trece de o revizuire sau cade tăcut la ea. HotPDF măsoară din colțul din stânga jos al paginii, cu Y crescând în sus, în puncte, la 72 pe inch. O pagină US Letter are 612 pe 792 de puncte; A4 are 595 pe 842. O margine de sus de un inch pe Letter pune, prin urmare, prima linie de bază lângă Y = 792 minus 72 minus dimensiunea fontului, nu la vreun număr mic de lângă partea de sus. Oricine vine dinspre coordonatele de ecran, unde Y crește în jos de la zero, scrie prima linie dincolo de marginea de jos și pierde zece minute întrebându-se unde s-a dus
Tratați aranjamentul ca pe o aritmetică față de ancore denumite, nu ca pe o coloană de numere magice. O margine stângă, o linie de bază curentă pe care o scădeți la fiecare rând și un interlinie fix transformă un bloc de etichete într-o buclă scurtă, în loc de un zid de literali:
const
LeftMargin = 72; // 1 inch de la margine
TopBaseline = 720; // primul rând, la ~1 inch de sus pe Letter
Leading = 16; // pasul vertical între rânduri
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 // s-a atins marginea de jos
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // fontul se resetează pe o pagină nouă
Y := TopBaseline;
end;
end;
end;
Garda de schimbare a paginii este linia pe care toată lumea o uită prima și pe care realitatea o lovește cel mai tare. Sub TextOut nu există niciun aranjament în flux. Coborâți dincolo de marginea de jos și textul continuă să se deseneze în jgheab, în afara paginii, în neant, fără niciun avertisment. Așa că îl urmăriți chiar dumneavoastră pe Y, apelați AddPage când trece de prag și resetați linia de bază. Apelul SetFont de după AddPage nu este umplutură opțională: fontul curent nu supraviețuiește unei schimbări de pagină, iar prima secvență de pe pagina nouă iese cu fontul implicit al vizualizatorului dacă îl omiteți
Spațierea între caractere și între cuvinte, pentru încadrare și aliniere
Uneori un șir este corect, dar are lățimea greșită: un antet care trebuie să acopere o linie fixă, un cod care ar trebui citit cu cifre mai aerisite, o coloană ale cărei valori trebuie împinse ca să se alinieze. PDF poartă doi operatori de stare a textului pentru asta, spațierea între caractere (Tc, spațiu suplimentar adăugat după fiecare glifă) și spațierea între cuvinte (Tw, spațiu suplimentar adăugat la fiecare caracter de spațiu), iar amândouă se exprimă în unități nescalate din spațiul textului, practic puncte la dimensiunea curentă a fontului. Ele sunt stare, nu argumente ale lui TextOut, deci le setați, desenați și le puneți la loc
// Spațiați literele unui antet scurt ca să se întindă peste o linie.
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); // resetați înainte de textul normal
// Lărgiți spațiile dintre cuvinte pe un singur rând lat.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
Spațierea între cuvinte acționează doar asupra caracterului de spațiu (codul 32), ceea ce are o consecință pe care merită să o știți: nu face nimic într-o secvență CJK fără spații ASCII și interacționează ciudat cu textul codificat ca indici de glife, nu ca octeți. Pentru ieșiri tabelare latine este calea ieftină de a lărgi golurile fără să rescrieți șirul. Spațierea între caractere este instrumentul mai bun pentru un antet care trebuie să atingă o lățime țintă, de vreme ce împrăștie ajustarea uniform peste fiecare glifă, în loc să o adune la spații
Resetarea este toată disciplina. Spațierea, ca și fontul, face parte din starea de desenare a paginii, iar starea persistă până când o schimbați. Spațiați literele unui antet și uitați să duceți valoarea la zero, iar fiecare paragraf de dedesubt moștenește întinderea, ceea ce se citește ca o greșeală subtilă, greu de localizat, care supraviețuiește unei corecturi în fugă și pică la una atentă. Obiceiul de încredere este să setați o valoare de spațiere, să desenați secvența care are nevoie de ea și să o puneți înapoi la zero pe rândul următor, astfel încât niciun cod ulterior să nu fie nevoit să știe ce a făcut o secțiune anterioară
Verificarea rezultatului acolo unde chiar se strică
Aranjarea textului se strică pe a doua mașină, nu pe prima, așa că verificările care contează se petrec departe de biroul dumneavoastră. Deschideți fișierul generat pe un sistem fără setul dumneavoastră de fonturi de dezvoltare instalat și confirmați că fonturile încorporate se randează în continuare, inclusiv literele latine cu diacritice, orice scrieri nelatine și semnele de punctuație, dintr-o singură trecere, nu verificând la întâmplare caracterele ușoare. Selectați și copiați câteva rânduri ca să confirmați că textul este text adevărat, nu contururi, ceea ce contează din clipa în care căutarea sau extragerea intră în discuție. Dați aranjamentului date reprezentative, cea mai lungă etichetă germană și cel mai lat număr, nu un substituent îngrijit, pentru că secvența care revarsă un câmp este întotdeauna cea pe care nu ați tastat-o de mână. Iar dacă pagina trebuie să aterizeze pe un formular pretipărit, tipăriți sau rasterizați o mostră și așezați-o peste original; o deviere de un sfert de milimetru a liniei de bază este invizibilă pe ecran și evidentă pe hârtie
Dacă nu ați scris încă nicio pagină, începeți cu exemplul HotPDF Hello World, care pregătește documentul, fontul și sistemul de coordonate cu originea în stânga jos de care depinde tot ce este mai sus. Apelurile TextOut, SetFont și cele de spațiere prezentate aici fac parte din HotPDF Delphi Component pentru Delphi și C++Builder