Tehnički članak

HotPDF TextOut u Delphi-ju: Velicina, stil, rotacija i razmak

Svaki vidljivi string u HotPDF dokumentu dolazi kroz jedan poziv: TextOut(X, Y, angle, Text). Primer Hello World koristi ga u najjednostavnijem obliku, font podesen jednom i cetiri argumenta ostavljeni na razumnim podrazumevanim vrednostima. Posle te prve stranice isti cetiri argumenta nose celokupan teret rasporeda. Treci argument rotira niz. Font podesen neposredno pre njega odlucuje velicinu i stil. A par X, Y, meren od ugla stranice u tackama, jedina je stvar koja stoji izmedzu cistog izvestaja i teksta koji se preklapa, seche ili klizi liniju nize na tudjim stampacima. Tu TextOut zaradjuje svoju primenu, i tu podrazumevane vrednosti prestaju biti dovoljne

Potpis vredi fiksirati u svesti pre svega ostalog: X i Y su Single u tackama, angle je Extended u stepenima, a Text je WideString, pa Unicode prolazi bez odvojenog poziva. Drugi preoptereceni oblik uzima PWORD plus duzinu za slucajeve kada vec drzite kodove glifova, ali za obicne stringove koristite WideString oblik

Velicina i stil dolaze iz SetFont, ne iz TextOut

TextOut nema parametar velicine. Velicina, tezina, nagib, sve to zivi u pozivu SetFont koji prethodi nizu, i ostaje na snazi dok ga sledeci SetFont ne zameni. To je jedina cinjenica koja objasnjava vecinu zbunjenosti prvog dana: linija izadje podebljana jer je tri poziva ranije nesto podesilo [fsBold] i nista to nije ocistilo

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

Drugi argument je skup TFontStyles, pa je [fsBold, fsItalic] podebljana kurziv, a [] je obicni tekst. Velicina je u tackama, ista jedinica kao koordinate, sto cini vertikalni razmak lakim za razumeti: linija od 12 tacaka zeli otprilike 14 do 16 tacaka vertikalnog koraka da dise, pa je smanjivanje Y za 14 po liniji razumni pocetni prored. Nema automatskog pomaka linije. Sami izracunavate svaku baznu liniju, sto je mukotrpno za paragraf ali tacno za obrazac gde svako polje sedi na fiksnoj koordinati

Dve prakticne napomene o imenu fonta. Razresava se u odnosu na fontove instalirane na masini za izgradnju, i ono sto OS vrati je ono sto se ugradi, pa ime koje se razresava na vasem radnom stolu i ime koje se razresava na serveru za izgradnju nisu garantovano ista lica. I font mora da pokriva skriptove u stringu. Niz ciriljice ili CJK teksta ispod lica koje podrzava samo latinicu renderuje se kao kutije za nedostajuci glif bez greske, sto je razlog zasto primer Hello World poseze za sirokim Unicode licem kada mesa jezike

HotPDF TextOut stranica sa Arial, Times New Roman i Courier New renderovanim u redovnom, podebljanom i kosim stilovima kroz nekoliko skupova karaktera

Argument ugla rotira oko sidra

Treci argument je onaj koji vecina koda zauvek ostavlja na nuli. Prosledite vrednost razlicitu od nule i niz se rotira suprotno od kazaljke sata oko svog sopstvenog sidra (X, Y), donjeg levog dela teksta, za toliko stepeni. Samo sidro se ne pomera, pa ista koordinata koja postavlja horizontalnu oznaku postavlja i njenu rotiranu dvojnicu; menja se samo smer u kome se glifovi krece

Dijagram HotPDF TextOut geometrije rotacije: nizovi na 0, 45 i 90 stepeni se okreću nasuprot kazaljci oko fiksnog dole-levo sidra, sa primerima Delphi TextOut poziva za oznake kičme, vodene žigove i nagnuta zaglavlja kolona
Nenulti ugao okreće niz suprotno od kazaljke oko svog nepomičnog sidra dole-levo, i deljene osnovne linije korakuju X tačno onako kako horizontalni redovi korakuju Y
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);

// Vertikalna oznaka ose uz levu marginu: 90 stepeni čita se odozdo nagore
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');

// Dijagonalni vodeni žig DRAFT preko tela stranice
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');

// Zaglavlja kolona nagnuta 60 stepeni da dugačke oznake stanu u usku tabelu
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');

Devedeset stepeni je uobicajen slucaj, oznaka koja tece uz stranu grafikona ili naslov na hrptu. Cetrdesetpet stepeni barata nagnutim zaglavljima kolona, trik koji omogucava siroj oznaci da stoji iznad uske kolone ne prelivajuci se u komsijine. Rotacija ne menja kako se sidro tumaci, sto ljude zbunjuje: niz od 90 stepeni i dalje pocinje od (X, Y) i raste od tamo nagore, pa da centirujete rotiranu oznaku menjate sidro, a ne ugao. Kada vise rotiranih nizova dele baznu liniju, dajte im isti Y i koracajte X, tacno kao sto biste koracali Y za poredane horizontalne linije

Postavljanje koordinata bez pogadjanja

Koordinate su deo koji prezivljava pregled ili ga tiho kvari. HotPDF meri od donjeg levog ugla stranice, Y raste nagore, u tackama po 72 po incu. US Letter stranica je 612 puta 792 tacke; A4 je 595 puta 842. Gornja margina od jednog inca na Letter postavlja prvu baznu liniju blizu Y = 792 minus 72 minus velicina fonta, a ne na neki mali broj blizu vrha. Svi koji dolaze iz ekranskih koordinata, gde Y raste nadole od nule, pisu prvu liniju van donje ivice i provode deset minuta pitajuci se gde je otisla

HotPDF: Dijagram US Letter strane koji pokazuje računicu osnovne linije sa LeftMargin 72, TopBaseline 720, i fiksnim Leading-om koji koraka ka podu donje margine na Y 72, pored petlje rasporeda sa imenovanim konstantama i njenom ručnom AddPage zaštitom i SetFont resetovanjem
Imenovana sidra pretvaraju kolonu magičnih brojeva u aritmetiku: umanjujte tekuću osnovnu liniju za Leading po redu i pod sami čuvajte sa AddPage

Tretirajte raspored kao aritmetiku prema imenovanim sidrima, a ne kao kolonu magicnih brojeva. Leva margina, tekuca bazna linija koju smanjujete po liniji, i fiksni prored pretvaraju blok oznaka u kratku petlju umesto u zid literala:

const
  LeftMargin = 72;        // 1 inch in
  TopBaseline = 720;       // prvi red, oko 1 inč naniže na Letter
  Leading = 16;            // vertikalni razmak između redova
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            // dostignuta donja margina
    begin
      Pdf.AddPage;
      Pdf.CurrentPage.SetFont('Arial', [], 11);  // font se ponovo postavlja na novoj stranici
      Y := TopBaseline;
    end;
  end;
end;

Cuvanje od prelaska stranice je linija koju svako prvo zaboravi, a terenska primena najteze pogadja. Ispod TextOut-a ne postoji raspored toka. Smanjite Y ispod donje margine i tekst nastavlja da se crta u marginu, van stranice, u nicosta, bez upozorenja. Stoga sami pratite Y, pozivate AddPage kada predje pod, i resetujete baznu liniju. SetFont posle AddPage nije opcionalno punjenje: trenutni font ne prezivljava prelom stranice, i prvi niz na novoj stranici izlazi u podrazumevanom licu pregledaca ako ga preskocite

Razmak karaktera i reci za uklapanje i poravnanje

Ponekad je string tacan ali pogresne sirine: zaglavlje koje mora da obuhvati fiksno pravilo, kod koji treba da se cita s prostranim ciframa, kolona kojoj vrednosti treba blago poravnati. PDF nosi dva operatora stanja teksta za ovo, razmak karaktera (Tc, dodatni prostor dodat posle svakog glifa) i razmak reci (Tw, dodatni prostor dodat na svakom karakteru razmaka), i oba su izrazena u neskaliranim jedinicama tekstualnog prostora, efektivno tackama pri trenutnoj velicini fonta. Oni su stanje, ne argumenti za TextOut, pa ih podeste, nacrtate, i vratite nazad

HotPDF: Razmak znakova Tc koji dodatni prostor ravnomerno širi posle svakog glyph-a SUMMARY naspram razmaka reči Tw koji ga grupiše samo na znakovima razmaka, povezano u ciklus set, draw, reset koji sprečava da stanje razmaka curi u kasnije pasuse
Tc razmaže svoje podešavanje preko svakog glifa dok Tw deluje samo na znak razmaka, i resetovanje u sledećem redu drži stanje crtanja čistim
// Rastegni razmak slova kratkog naslova da se proteže preko linije
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);   // ponovo postavi pre običnog teksta

// Povećaj razmake između reči u jednom širokom redu
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name        Department        Extension');
Pdf.CurrentPage.SetWordSpacing(0);

Razmak reci deluje samo na karakter razmaka (kod 32), sto ima posledicu vrednu znanja: ne cini nista unutar CJK niza koji nema ASCII razmake, i cudan je u interakciji s tekstom kodiranim kao indeksi glifova umesto bajtova. Za latinicni tabelarni izlaz, to je jeftin nacin prosirenja razmaka bez prekucavanja stringa. Razmak karaktera je bolji alat za zaglavlje koje mora da dosegne ciljanu sirinu, jer ravnomerno rasporeduje podesavanje kroz svaki glif umesto da ga gomila na razmacima

Reset je celokupna disciplina. Razmak, poput fonta, deo je stanja crtanja stranice, i stanje se odrzava dok ga ne promenite. Razmak u jednom zaglavlju i zaboravljanje da ga ponistite znaci da svaki paragraf ispod nasledjuje rastezanje, sto se cita kao suptilna, tesko smestiva pogresnost koja prezivljava povrsno korigovanje i pada na pazljivo. Pouzdan obicaj je postavljanje vrednosti razmaka, crtanje niza koji je treba, i vracanje na nulu u sledecem redu, tako da kasniji kod ne mora znati sta je raniji odeljak uradio

HotPDF TextOut stranica koja poredi horizontalno skaliranje teksta, razmak karaktera, razmak reci i rezimi popune nasuprot konture

Proveravanje izlaza tamo gde zapravo puca

Raspored teksta pada na drugoj masini, a ne na prvoj, pa provere koje su vazne dogadjaju se van vaseg stola. Otvorite generisanu datoteku na sistemu bez vaseg developerskog skupa fontova i potvrdite da se ugradjena lica i dalje renderuju, ukljucujuci akcentovani latinski, sve ne-latinicne skriptove i interpunkciju, u jednom prolazu umesto spot-proveravanja jednostavnih karaktera. Selektujte i kopirajte nekoliko linija da potvrdite da je tekst pravi tekst a ne konture, sto postaje vazno cim pretrazivanje ili ekstrakcija dodju u obzir. Nahranite raspored reprezentativnim podacima, najduzu nemacku oznaku i najsiri broj, a ne uredni placeholder, jer je niz koji prekoracuje polje uvek onaj koji niste rucno uneli. I ako stranica mora da sletii na unapred stampan obrazac, odstampajte ili rasterizujte jedan uzorak i uporediteg s originalom; pomak bazne linije od cetvrt milimetra je nevidljiv na ekranu i ocit na papiru

Ako jos niste napisali ni jednu stranicu, pocnite s primerom HotPDF Hello World, koji podesen dokument, font i koordinatni sistem donjeg levog ugla od koga sve gore zavisi. Pozivi TextOut, SetFont i razmaka prikazani ovde deo su HotPDF Delphi Component za Delphi i C++Builder