Kiekviena matoma eilutė HotPDF dokumente atsiranda per vieną iškvietimą: TextOut(X, Y, angle, Text). Hello World pavyzdyje jis naudojamas paprasčiausiu būdu: šriftas nustatomas vieną kartą, o keturi argumentai paliekami su numatytosiomis reikšmėmis. Tačiau už pirmojo puslapio ribų šie keturi argumentai perima visą maketo valdymą. Trečiasis argumentas pasuka tekstą. Prieš jį nustatytas šriftas lemia dydį ir stilių. O X ir Y koordinačių pora, matuojama taškais nuo puslapio kampo, yra vienintelis dalykas, skiriantis tvarkingą ataskaitą nuo teksto, kuris persidengia, yra nukerpamas arba pasislenka viena eilute žemiau kito vartotojo spausdintuve. Čia ir atsiskleidžia TextOut nauda, o numatytųjų nustatymų nebepakanka.
Pirmiausia verta įsiminti metodo struktūrą: X ir Y yra Single tipo reikšmės taškais (points), angle yra Extended tipo reikšmė laipsniais, o Text yra WideString, todėl Unicode simboliai perduodami be papildomų iškvietimų. Antroji perkrauta metodo versija (overload) priima PWORD ir ilgį, kai jau turite glifų kodus, tačiau įprastoms eilutėms naudojama WideString forma.
Dydis ir stilius nustatomi per SetFont, o ne TextOut
TextOut neturi dydžio parametro. Dydis, storis, pasvirimas – visa tai nustatoma SetFont iškvietimu prieš išvedant tekstą, ir ši būsena lieka galioti tol, kol ją pakeičia kitas SetFont. Šis vienintelis faktas paaiškina dažniausią pradedančiųjų klaidą: eilutė atspausdinama paryškinta, nes prieš tris iškvietimus buvo nustatyta [fsBold] būsena ir ji nebuvo išvalyta.
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
Antrasis argumentas yra TFontStyles aibė, todėl [fsBold, fsItalic] reiškia paryškintą kursyvą, o [] – paprastą tekstą. Dydis nurodomas taškais (points) – tais pačiais vienetais, kaip ir koordinatės, todėl lengva apskaičiuoti tarpus tarp eilučių: 12 taškų šrifto eilutei reikia maždaug 14–16 taškų vertikalaus žingsnio, todėl Y koordinatės mažinimas 14 taškų kiekvienai eilutei yra geras atskaitos taškas. Čia nėra automatinio perėjimo į kitą eilutę. Kiekvieną bazinę liniją turite apskaičiuoti patys, kas gali būti nepatogu pastraipoms, tačiau labai tikslu formoms, kur kiekvienas laukas turi būti fiksuotoje koordinatėje.
Dvi praktinės pastabos dėl šrifto pavadinimo. Šriftas ieškomas tarp sistemoje, kurioje kuriamas dokumentas, įdiegtų šriftų, ir tai, ką grąžina operacinė sistema, įterpiama į failą. Todėl nėra garantijos, kad pavadinimas, kuris veikia jūsų kompiuteryje, atitiks tą patį šriftą kūrimo serveryje. Be to, šriftas turi palaikyti eilutėje naudojamus simbolius. Kirilica arba CJK tekstas su tik lotyniškus simbolius palaikančiu šriftu bus atvaizduojami kaip tušti kvadratėliai be jokių pranešimų apie klaidą, todėl Hello World pavyzdyje naudojamas platus Unicode šriftas, kai maišomos kalbos.
Argumentas angle pasuka tekstą aplink tvirtinimo tašką
Trečiasis argumentas yra tas, kurį dauguma programuotojų visada palieka lygų nuliui. Perdavus ne nulinę reikšmę, tekstas pasukamas prieš laikrodžio rodyklę aplink savo (X, Y) tvirtinimo tašką (apatinį kairįjį teksto kampą) nurodytu laipsnių skaičiumi. Pats tvirtinimo taškas nejuda, todėl ta pati koordinatė, kuri nustatė horizontalaus užrašo vietą, nustato ir pasukto teksto vietą – pasikeičia tik glifų kryptis.
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');
Dažniausiai naudojamas 90 laipsnių kampas – pavyzdžiui, užrašams šalia vertikalios diagramos ašies arba ant knygos nugarėlės. 45 laipsnių kampas tinka pakreiptoms stulpelių antraštėms – tai gudrybė, leidžianti ilgam užrašui tilpti virš siauro stulpelio nepersidengiant su gretimais. Pasukimas nekeičia tvirtinimo taško interpretacijos, kas kartais klaidina programuotojus: 90 laipsnių kampu pasuktas tekstas vis tiek prasideda nuo (X, Y) ir kyla į viršų, todėl norint centruoti pasuktą užrašą, reikia koreguoti tvirtinimo tašką, o ne kampą. Kai keli pasukti užrašai dalijasi ta pačia bazine linija, suteikite jiems tą pačią Y koordinatę ir keiskite X, panašiai kaip keistumėte Y horizontalioms eilutėms.
Koordinačių nustatymas be spėliojimo
Koordinatės yra ta dalis, kuri arba sėkmingai praeina patikrą, arba tyliai sugadina visą darbą. HotPDF matuoja nuo apatinio kairiojo puslapio kampo (Y didėja į viršų) taškais (points), kurių colyje yra 72. US Letter formato puslapis yra 612 x 792 taškų dydžio; A4 – 595 x 842. Todėl vieno colio viršutinė paraštė Letter formate reiškia, kad pirmoji bazinė linija bus ties Y = 792 minus 72 minus šrifto dydis, o ne ties kokiu nors nedideliu skaičiumi viršuje. Kiekvienas, atėjęs iš ekrano koordinačių sistemos, kur Y didėja žemyn nuo nulio, pirmąją eilutę nubrėžia už apatinio krašto ir dešimt minučių svarsto, kur ji dingo.
Vertinkite maketavimą kaip aritmetiką su pavadintais tvirtinimo taškais, o ne kaip magiškų skaičių stulpelį. Kairioji paraštė, kintanti bazinė linija, kurią mažinate kiekvienai eilutei, ir fiksuotas žingsnis tarp eilučių paverčia užrašų bloką trumpu ciklu, o ne kodo literais:
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;
Puslapio pabaigos apsauga yra ta kodo eilutė, kurią visi pamiršta pirmiausia, ir tai skaudžiausiai atsiliepia realiame darbe. Po TextOut nėra jokio automatinio turinio išdėstymo. Sumažinkite Y žemiau apatinės paraštės ir tekstas bus piešiamas už puslapio ribų, į niekur, be jokių įspėjimų. Todėl turite patys stebėti Y koordinatę, iškviesti AddPage, kai ji pasiekia ribą, ir nustatyti bazinę liniją iš naujo. Šrifto nustatymas su SetFont po AddPage nėra pasirenkamas dalykas: esamas šriftas neišlieka po puslapio lūžio, ir pirmasis naujo puslapio tekstas bus nubraižytas numatytuoju šriftu, jei šį žingsnį praleisite.
Simbolių ir žodžių tarpai pritaikymui ir lygiavimui
Kartais eilutė yra teisinga, tačiau netinkamo pločio (pavyzdžiui, antraštė turi apimti fiksuotą plotį, kodą reikėtų skaityti su didesniais tarpais tarp skaitmenų arba stulpelio reikšmes reikia šiek tiek pastumti lygiavimui). PDF palaiko du teksto būsenos operatorius: simbolių tarpus (character spacing - Tc, papildomas tarpas pridedamas po kiekvieno glifo) ir žodžių tarpus (word spacing - Tw, papildomas tarpas pridedamas prie kiekvieno tarpo simbolio). Abu jie išreiškiami nesukalibruotais teksto erdvės vienetais, t. y. taškais esamam šrifto dydžiui. Tai yra būsenos, o ne TextOut argumentai, todėl juos nustatote, nubraižote tekstą ir nustatote atgal.
// 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);
Žodžių tarpai veikia tik tarpo simbolį (kodas 32), kas turi svarbią pasekmę: tai nieko nedaro CJK tekste, kuriame nėra ASCII tarpų, ir keistai veikia su tekstu, kuris koduojamas glifų indeksais, o ne baitais. Lotyniškiems lentelės duomenims tai yra paprastas būdas padidinti tarpus neperrašant eilutės. Simbolių tarpai yra geresnis įrankis antraštei, kuri turi pasiekti tam tikrą plotį, nes pakeitimas paskirstomas tolygiai visiems glifams, o ne sutelkiamas ties tarpais.
Būsenos atstatymas yra labai svarbi taisyklė. Tarpai, kaip ir šriftas, yra puslapio braižymo būsenos dalis, o ši būsena išlieka tol, kol ją pakeičiate. Padidinkite vienos antraštės simbolių tarpus ir pamirškite juos anuliuoti, ir kiekviena pastraipa žemiau paveldės šį ištempimą, kas atrodys keistai ir sugadins maketą. Patikimas įprotis – nustatyti tarpų reikšmę, išvesti reikiamą tekstą ir iškart po to nustatyti ją atgal į nulį, kad vėlesniam kodui nereikėtų žinoti, ką atliko ankstesnis kodo blokas.
Išvesties tikrinimas ten, kur ji dažniausiai sugenda
Teksto maketas sugenda antrame kompiuteryje, o ne pirmame, todėl svarbiausi patikrinimai turi vykti toliau nuo jūsų darbo stalo. Atidarykite sugeneruotą failą sistemoje, kurioje nėra jūsų, kaip programuotojo, šriftų rinkinio, ir įsitikinkite, kad įterpti šriftai vis tiek atvaizduojami – įskaitant lotyniškus simbolius su diakritiniais ženklais, ne lotyniškus rašmenis ir skyrybos ženklus. Pasirinkite ir nukopijuokite kelias eilutes, kad įsitikintumėte, jog tai yra tikras tekstas, o ne linijų kontūrai, kas yra svarbu atliekant paiešką ar teksto išgavimą. Užpildykite maketą realiais duomenimis (pavyzdžiui, ilgiausiu vokišku užrašu ir plačiausiu skaičiumi), o ne tvarkingais pavyzdžiais, nes lauką perpildo būtent tas tekstas, kurio neįvedėte rankiniu būdu. O jei puslapis turi atitikti iš anksto atspausdintą formą, atspausdinkite arba rasterizuokite vieną pavyzdį ir uždėkite jį ant originalo; ketvirčio milimetro nuokrypis ekrane nepastebimas, tačiau popieriuje akivaizdus.
Jei dar neparašėte nei vieno puslapio, pradėkite nuo HotPDF Hello World pavyzdžio, kuris nustato dokumentą, šriftą ir apatinę kairiąją koordinačių sistemą, nuo kurios priklauso visi aukščiau aprašyti veiksmai. Čia parodyti TextOut, SetFont ir tarpų iškvietimai yra HotPDF komponento, skirto Delphi ir C++Builder, dalis.