Tehnički članak

PDF anotacije u Delphiju uz HotPDF: Vrste i okviri

Anotacija nije sadržaj stranice. Kada pozovete TextOut ili nacrtate pravokutnik, oznake postaju dio toka sadržaja stranice, zapečene u bajtove koje render slika. Anotacija je zaseban rječnik koji visi sa stranice kroz njezin niz /Annots, s vlastitim pravokutnikom, vlastitim izgledom, i vlastitim životnim ciklusom. Čitatelj je može otvoriti, premjestiti, sakriti, ili ukloniti bez dodirivanja ijednog glifa na stranici ispod nje. Ta odvojenost je cijeli razlog zašto anotacije postoje, i to je također izvor dviju stvari koje ljude prve iznenade: gdje anotacija slijeće, i kako izgleda jednom kada je se dočepa određeni preglednik

HotPDF izlaže ISO 32000 podvrste anotacija kroz obitelj AddXxxAnnotation poziva na objektu stranice. Sve one dijele isti oblik: pravokutnik koji fiksira anotaciju na stranici u PDF korisničkom prostoru, neku nosivost (payload) (tekst, naziv pečata, par točaka), i boju. Postavite pravokutnik ispravno i većina posla je gotova. Ostatak je poznavanje koje podvrste nose svoj vlastiti izgled a koje se oslanjaju na preglednik da ih nacrta

PDF stranica proizvedena pomoću HotPDF-a prikazuje ikone tekstualnih bilješki, okvire slobodnog teksta, kvadratne i linijske oznake, te pečate odobrenja smještene preko stranice
Jedna stranica koja nosi nekoliko podvrsta anotacija odjednom: tekstualne bilješke, slobodan tekst, geometrijske oznake, i pečate

Pravokutnik je anotacija, a ne tekst

Svaki poziv za anotaciju uzima TRect, i taj pravokutnik znači nešto drugo od koordinata koje proslijedite u TextOut. Za tekstualnu bilješku to je klikabilna vruća točka (hotspot), mala regija gdje ikona bilješke sjedi i gdje klik otvara komentar. Za kvadrat ili okvir slobodnog teksta to je vidljivi opseg oznake. Za pečat to je okvir u koji je umjetnički prikaz (art) pečata skaliran. Brojevi su PDF korisnički prostor bodova, izmjereni od donjeg lijevog kuta stranice s Y-om koji se povećava prema gore, ista konvencija koju koristi ostatak HotPDF-a

Tekstualna bilješka je najlakša podvrsta. Date joj tekst tijela, pravokutnik za ikonu, zastavicu (flag) za to da li se otvara prema zadanim postavkama, naziv ikone, i boju

Pdf.CurrentPage.AddTextAnnotation(
  'Reviewer: confirm the totals on this line before sign-off.',
  Rect(120, 700, 140, 720),   // icon hotspot, ~20pt square
  False,                      // closed until the reader clicks it
  taComment,                  // bubble icon
  clBlue);

Pravokutnik je ovdje namjerno mali, oko dvadeset točaka na jednoj strani, zato što je tekstualna bilješka samo ikona dok na nju netko ne klikne. Učinite pravokutnik velikim i nećete dobiti veliku bilješku; dobivate predimenzioniranu metu klika s ikonom prikvačenom na jedan kut. Zastavica Open kontrolira hoće li se skočni prozor prikazivati kada se dokument učita. Postavite pregršt bilješki na True i one će se slagati jedna na drugu i na vrh sadržaja, pa to rezervirajte za onu jednu bilješku koju zapravo želite da čitatelj odmah vidi

Naziv ikone dolazi od THPDFTextAnnotationType, koji se preslikava na standardne ikone bilješki: taComment, taKey, taNote, taHelp, taParagraph, taNewParagraph, i taInsert. Ikona je jedina stvar koju vrsta mijenja. Ne mijenja ponašanje, i vrijedi znati da ne iscrtava svaki preglednik svih sedam; sigurne među starim i novim čitačima su taComment, taNote, i taHelp

Slobodan tekst se piše na stranicu, ali ostaje anotacija

Anotacija slobodnog teksta izgleda kao sadržaj zato što je tekst vidljiv bez klika, sjedeći u svom pravokutniku kao natpis. To je još uvijek anotacija, sa svom odvojivošću koju to podrazumijeva, što je točno ono što želite za pečat pregleda ili oznaku nacrta (draft label) koju bi netko trebao moći kasnije ukloniti. Potpis zamjenjuje ikonu i zastavicu otvaranja vrijednošću poravnanja (justification)

Pdf.CurrentPage.AddFreeTextAnnotation(
  'DRAFT - not for distribution',
  Rect(200, 210, 400, 235),   // the box the text is laid into
  ftCenter,                   // ftLeftJust / ftCenter / ftRightJust
  clRed);

Ovdje je pravokutnik važniji nego što je to za tekstualnu bilješku, zato što se tekst prelama i poravnava unutar njega. Ako je okvir prekratak tekst će se odsjeći (clips) na donjem rubu; preuzak i prelamat će se na mjestima na koja niste namjeravali. Poravnanje dolazi iz THPDFFreeTextAnnotationJust i ima samo tri vrijednosti. Budući da je slobodan tekst oznaka anotacije (markup annotation), čitatelj koji otvori datoteku u uređivaču može ga odabrati, premjestiti, ili izbrisati kao cjelinu, što je razlika koja odlučuje hoćete li posegnuti za slobodnim tekstom ili samo nacrtati riječi pomoću TextOut. Ako oznaka mora biti trajna, nacrtajte je. Ako je urednička (editorial) i namijenjena skidanju, učinite je anotacijom

Geometrijske i linijske oznake za pokazivanje na stvari

Kvadrat, krug, i linija su oznake koje koristite da biste pokazali na neku regiju umjesto da je opisujete riječima. AddCircleSquareAnnotation pokriva oblike dvaju okvira putem THPDFCSAnnotationType od csCircle ili csSquare, s pravokutnikom koji daje granice oblika

// A box drawn around a figure that needs attention
Pdf.CurrentPage.AddCircleSquareAnnotation(
  'Check this region against the source data',
  Rect(50, 300, 120, 360),
  csSquare,
  clGreen);

// A line, given two points rather than a rectangle
var
  StartPt, EndPt: THPDFCurrPoint;
begin
  StartPt.X := 130; StartPt.Y := 360;
  EndPt.X   := 250; EndPt.Y   := 320;
  Pdf.CurrentPage.AddLineAnnotation(
    'Points from the note to the figure',
    StartPt, EndPt,
    clBlue);
end;

Primijetite da linijska anotacija razbija uzorak pravokutnika: uzima dva THPDFCurrPoint zapisa, početak i kraj, zato što je linija definirana svojim krajnjim točkama, a ne graničnim okvirom (bounding box). Boja postavlja potez (stroke). Ako želite vrhove strelica (arrowheads), HotPDF ima overload (preopterećenje) funkcije AddLineAnnotation koja prihvaća stilove završetaka linije, ali običan oblik s tri argumenta iscrtava golu liniju, što je obično ono što pokazivač (callout) želi

Podvrste oznaka teksta (Text-markup subtypes) rade na regiji koju ste već položili (laid out). AddHighlightAnnotation uzima pravokutnik, neobavezni sadržaj, i boju kojoj je žuta zadana vrijednost, i oboji (tints) područje na način na koji bi to učinio marker. Namijenjena je sjedenju preko stvarnog teksta, pa bi pravokutnik trebao odgovarati granicama riječi koje ste nacrtali, što znači da je obično izračunavate iz istih koordinata koje ste proslijedili u TextOut umjesto nagađanja

Pečati ovise o pregledniku za njihovo renderiranje

Anotacija pečata (stamp annotation) je ona koja će najvjerojatnije izgledati različito od jednog do drugog čitača, a razlog tome je vrijedan razumijevanja. AddStampAnnotation imenuje standardni pečat preko THPDFStampAnnotationType, s vrijednostima kao što su satApproved, satConfidential, satFinal, satDraft, i satForComment

Pdf.CurrentPage.AddStampAnnotation(
  'Approved for release on review',
  Rect(50, 400, 200, 440),
  satApproved,
  clGreen);

Naziv pečata je zahtjev. PDF definira skup standardnih imena pečata, ali ne i umjetnički prikaz iza njih, tako da svaki preglednik dolazi sa svojim vlastitim renderiranjem za "APPROVED" ili "CONFIDENTIAL," a neki uopće ne prikazuju ništa za ona imena koja ne prepoznaju. Pravokutnik kontrolira okvir u koji se crtež skalira, a boja je nagovještaj koji preglednik može i ne mora poštovati. Ako pečat mora izgledati identično svugdje, pouzdana ruta uopće nije standardni pečat: nacrtajte oznaku sami s TextOut i pozivima za iscrtavanje, ili je postavite kao anotaciju slobodnog teksta čiji izgled vi sami kontrolirate. Posegnite za standardnim pečatom kada želite onaj poznati izgled samog preglednika i kada vam varijacije nisu toliki problem

Privitci (attachments) datoteka prate isti oblik - pravokutnik plus payload (nosivost). AddFileAttachmentAnnotation uzima taj neki opis, pa samu putanju datoteke koju se želi ugraditi, potom određeni jedan pravokutnik namijenjen za onu pa takvu ikonu u obliku spajalice (paperclip icon), kao na koncu i boju. Datoteka tu potom pak jaše (rides) s tim svime u tako kreiranom PDF-u, dok je pritom ta tako zadana ikona ona ručica (handle) a koju onda onaj krajnji tu pa čitatelj i na nju klikne i iskoristi onda to a da bi izvadio (extract) onaj taj njezin pripadajući privitak

Kako se anotacije razlikuju od AcroForm polja

Zabuna (confusion) koja stoji najviše vremena je tretiranje anotacije kao da se tu ustvari zapravo radi i o nekakvom polju obrasca (form field). Oboje se spajaju na stranicu preko /Annots, i polje obrasca je zapravo tu jedna i pa u biti specijalna (special) odnosno posebna neka podvrsta (subtype) takve jedne anotacije (takozvani widget element), to jest upravo i razlog zbog koje bi one i izgledale srodno (related). No, one tu pritom ipak nikako nikad pak nisu međusobno izmjenjive (interchangeable). Polje obrasca ono drži s tim u sebi vrijednost, ima jedno od dano pa njoj to uza to njeno isto jedno svoje joj neko a isto i ime (name), pa s tim usput i potom a u tom redoslijedu kartica (tab order) i tu u to isto isto tako aktivno pak na i svemu sudjeluje, a isto ga na tom možete i poslati (submit), resetirati, ili na nju nadodati taj to njoj isto takvo pa zadano isto pak to tu za nju njeno neko njoj namijenjeno po o skriptirati (scripted); vi sve takve stvari onda isto na tu stvarate odnosno u i a po kreirate uz korištenje pa i pomoć od samo tu po takvih na o ovdje isto spominjanih poziva a po istom pa tome o kakvima se (calls) poput AddTextField, AddCheckBox, i AddPushButton, a ne pak pozivima anotacija na ovoj stranici. Markup anotacija drži samo neki taj vaš komentar (comment) ili možda koji kakav vaš tek jedan tu isto pak taj zadani joj tako jedan pak taj isti takav njoj u o i pa tu tek taj obični oblik (shape), ona sama takva pa po sebi dakle u biti to nema neku u i za nju u po takvu vrijednost po koju bi pak vi na tu tu trebali to jest tu poslati i proslijediti nju vama o tu negdje gdje vam je to pak isto i bitno, pa zbog svega baš ovoga tog je upravo ona sasvim krivi alat (wrong tool) u baš o tu pa tom trenutku (moment) o u i baš onom kada zapravo trebate tu i pa u prikupiti taj vaš ulaz (collect input)

Praktični test je jednostavan. Ako je korisnik taj od kojega se u biti ustvari onda namijenjeno (meant to type) da i natipka, potom odabere (choose) ili pak klikne (click) i uz to pak želi da dokument zapamti to (have the document remember it), vi u tom slučaju želite (you want) AcroForm polje (AcroForm field). Ako ostavljate (you are leaving) bilješku (a note), označavate (marking) regiju (a region), ili udarate pečatom (stamping) status (a status) koji putuje (travels) sa datotekom, ali nije podatak (but is not data), vi želite anotaciju (you want an annotation). Njihovo miješanje (Mixing them up) proizvodi (produces) dokumente koji izgledaju ispravno (look right) i ponašaju se pogrešno (and behave wrong): "polje" (field) koje nitko ne može popuniti (nobody can fill), ili komentar koji nestane kada obrazac bude resetiran (or a comment that vanishes when a form is reset). Interaktivna strana (The interactive side), sa vrstama polja (with field types), validacijom, i akcijama slanja (and submit actions), njezina je vlastita tema (is its own subject) pokrivena u vodiču za AcroForm polja i akcije (AcroForm fields and actions walkthrough)

Sastavljanje stranice

Dijelovi se slažu (compose) na način na koji to radi i ostatak (the rest of HotPDF does) HotPDF-a. Postavite svojstva (Set document properties) dokumenta, pozovite BeginDoc, nacrtajte sadržaj (draw whatever page content you need) stranice koji vam treba uz pozive teksta i grafike (with the text and graphics calls), dodajte anotacije (add annotations) na vrh (on top), i zatvorite sa EndDoc. Anotacije se kače na (attach to) CurrentPage, pa nakon AddPage slijeću na (they land on) novu stranicu, i bilješka koju ste namijenili za (you meant for) stranicu jedan tiho će se pojaviti na stranici dva ako ju dodate nakon prijeloma (after the break)

Pdf := THotPDF.Create(nil);
try
  Pdf.FileName := 'annotated.pdf';
  Pdf.Compression := cmFlateDecode;
  Pdf.FontEmbedding := True;
  Pdf.BeginDoc;

  Pdf.CurrentPage.SetFont('Arial', [], 11);
  Pdf.CurrentPage.TextOut(50, 740, 0, 'Quarterly figures, draft for review');

  Pdf.CurrentPage.AddTextAnnotation(
    'Confirm the totals before sign-off.',
    Rect(50, 720, 70, 740), False, taComment, clBlue);
  Pdf.CurrentPage.AddFreeTextAnnotation(
    'DRAFT', Rect(450, 720, 540, 745), ftCenter, clRed);
  Pdf.CurrentPage.AddStampAnnotation(
    'For comment', Rect(50, 660, 180, 695), satForComment, clGreen);

  Pdf.EndDoc;
finally
  Pdf.Free;
end;

Jedan zadnji refleks koji se isplati izgraditi (One last reflex worth building) kada izlaz izgleda pogrešno (when output looks wrong): otvorite datoteku u više od jednog preglednika prije nego što odlučite (before you decide) da kod ne valja (the code is broken). Pečati i rjeđe ikone bilješki su uobičajeni krivci (usual culprits), i budući da je anotacija zahtjev (request) čitaču umjesto (rather than) naslikanih piksela (painted pixels), razlika između Acrobata i laganog preglednika često je specifikacija koja radi onako kako je zamišljeno (working as designed), a ne bug u vašem pozivu

Pozivi anotacija prikazani ovdje dio su komponente HotPDF Component za Delphi i C++Builder