Articol tehnic

Adnotări PDF în Delphi cu HotPDF: tipuri și dreptunghiuri

O adnotare nu este conținut de pagină. Când apelați TextOut sau desenați un dreptunghi, urmele devin parte din fluxul de conținut al paginii, coapte în octeții pe care îi pictează un randor. O adnotare este un dicționar separat, care atârnă de pagină prin tabloul ei /Annots, cu propriul dreptunghi, propriul aspect și propriul ciclu de viață. Un cititor o poate deschide, muta, ascunde sau scoate fără să atingă o singură glifă din pagina de dedesubt. Acea separare este chiar motivul pentru care există adnotările și este totodată sursa celor două lucruri care surprind lumea prima dată: unde aterizează o adnotare și cum arată ea odată ce pune mâna pe ea un anumit vizualizator

HotPDF expune subtipurile de adnotări din ISO 32000 printr-o familie de apeluri AddXxxAnnotation pe obiectul pagină. Toate au aceeași formă: un dreptunghi care fixează adnotarea pe pagină în spațiul utilizator PDF, o încărcătură oarecare (text, un nume de ștampilă, o pereche de puncte) și o culoare. Nimeriți dreptunghiul și cea mai mare parte a muncii este gata. Restul înseamnă să știți care subtipuri își poartă propriul aspect și care se bazează pe vizualizator ca să le deseneze

O pagină PDF produsă de HotPDF, care arată pictograme de note de text, casete de text liber, marcaje pătrate și liniare și ștampile de aprobare, plasate pe toată pagina
O singură pagină care poartă deodată mai multe subtipuri de adnotări: note de text, text liber, marcaje geometrice și ștampile

Dreptunghiul este adnotarea, nu textul

Fiecare apel de adnotare primește un TRect, iar acel dreptunghi înseamnă altceva decât coordonatele pe care le transmiteți lui TextOut. Pentru o notă de text, el este zona activă la clic, mica regiune în care stă pictograma notei și în care un clic deschide comentariul. Pentru un pătrat sau o casetă de text liber, el este întinderea vizibilă a marcajului. Pentru o ștampilă, el este caseta în care se scalează grafica ștampilei. Numerele sunt puncte din spațiul utilizator PDF, măsurate din colțul din stânga jos al paginii, cu Y crescând în sus, aceeași convenție pe care o folosește tot restul HotPDF

O notă de text este subtipul cel mai ușor. Îi dați textul din corp, un dreptunghi pentru pictogramă, un indicator care spune dacă se deschide implicit, un nume de pictogramă și o culoare

Pdf.CurrentPage.AddTextAnnotation(
  'Reviewer: confirm the totals on this line before sign-off.',
  Rect(120, 700, 140, 720),   // zona activă a pictogramei, pătrat de ~20pt
  False,                      // închisă până când cititorul dă clic
  taComment,                  // pictogramă de bulă
  clBlue);

Dreptunghiul de aici este mic intenționat, cam douăzeci de puncte pe latură, pentru că o notă de text este doar o pictogramă până când cineva dă clic pe ea. Faceți dreptunghiul mare și nu obțineți o notă mare; obțineți o țintă de clic supradimensionată, cu pictograma prinsă într-un colț. Indicatorul Open stabilește dacă popupul se vede la încărcarea documentului. Setați câteva note pe True și ele se stivuiesc una peste alta și peste conținut, așa că rezervați asta pentru singura notă pe care chiar vreți ca cititorul să o vadă imediat

Numele pictogramei vine din THPDFTextAnnotationType, care se mapează pe pictogramele standard de notă: taComment, taKey, taNote, taHelp, taParagraph, taNewParagraph și taInsert. Pictograma este singurul lucru pe care îl schimbă tipul. El nu modifică comportamentul, iar merită știut că nu orice vizualizator le desenează pe toate șapte; cele sigure în cititoarele vechi și noi deopotrivă sunt taComment, taNote și taHelp

Textul liber scrie pe pagină, dar rămâne adnotare

O adnotare de text liber arată ca un conținut, pentru că textul este vizibil fără clic, stând în dreptunghiul lui ca o legendă. Rămâne totuși o adnotare, cu toată separabilitatea pe care asta o presupune, ceea ce este exact ce vă doriți pentru o ștampilă de recenzie sau o etichetă de ciornă pe care cineva ar trebui să o poată scoate mai târziu. Semnătura schimbă pictograma și indicatorul de deschidere pentru o valoare de aliniere

Pdf.CurrentPage.AddFreeTextAnnotation(
  'DRAFT - not for distribution',
  Rect(200, 210, 400, 235),   // caseta în care este așezat textul
  ftCenter,                   // ftLeftJust / ftCenter / ftRightJust
  clRed);

Aici dreptunghiul contează mai mult decât la o notă de text, pentru că textul se împarte pe rânduri și se aliniază în interiorul lui. Faceți caseta prea scundă și textul se taie la marginea de jos; prea îngustă și se rupe în locuri pe care nu le-ați intenționat. Alinierea vine din THPDFFreeTextAnnotationJust și are doar cele trei valori. Fiindcă textul liber este o adnotare de marcaj, un cititor care deschide fișierul într-un editor o poate selecta, muta sau șterge ca unitate, iar aceasta este diferența care hotărăște dacă apelați la text liber sau desenați pur și simplu cuvintele cu TextOut. Dacă eticheta trebuie să fie permanentă, desenați-o. Dacă este editorială și menită să iasă, faceți-o adnotare

Marcaje geometrice și liniare pentru a arăta spre lucruri

Pătratele, cercurile și liniile sunt marcajul cu care arătați spre o regiune, în loc să o descrieți în cuvinte. AddCircleSquareAnnotation acoperă cele două forme de casetă printr-un THPDFCSAnnotationType de csCircle sau csSquare, dreptunghiul dând limitele formei

// O casetă desenată în jurul unei figuri care are nevoie de atenție
Pdf.CurrentPage.AddCircleSquareAnnotation(
  'Check this region against the source data',
  Rect(50, 300, 120, 360),
  csSquare,
  clGreen);

// O linie, dată prin două puncte, nu printr-un dreptunghi
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;

Observați că adnotarea de linie rupe tiparul dreptunghiului: ea primește două înregistrări THPDFCurrPoint, un început și un sfârșit, pentru că o linie este definită prin capetele ei, nu printr-o casetă de încadrare. Culoarea stabilește conturul. Dacă vreți vârfuri de săgeată, HotPDF are supraîncărcări ale lui AddLineAnnotation care acceptă stiluri de capăt de linie, dar forma simplă cu trei argumente desenează o linie goală, care de obicei este exact ce vrea o casetă de explicație

Subtipurile de marcare a textului lucrează pe o regiune pe care ați așezat-o deja. AddHighlightAnnotation primește un dreptunghi, un conținut opțional și o culoare implicit galbenă și colorează zona așa cum ar face-o un marker. Este menită să stea peste text real, deci dreptunghiul ar trebui să corespundă limitelor cuvintelor pe care le-ați desenat, ceea ce înseamnă că de obicei îl calculați din aceleași coordonate pe care le-ați transmis lui TextOut, în loc să îl ghiciți

Ștampilele depind de vizualizator ca să fie randate

Adnotarea de tip ștampilă este cea mai predispusă să arate diferit de la un cititor la altul, iar motivul merită înțeles. AddStampAnnotation numește o ștampilă standard prin THPDFStampAnnotationType, cu valori precum satApproved, satConfidential, satFinal, satDraft și satForComment

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

Numele ștampilei este o cerere. PDF definește setul de nume standard de ștampile, dar nu și grafica din spatele lor, așa că fiecare vizualizator livrează propria randare a lui „APPROVED” sau „CONFIDENTIAL”, iar câteva nu randează nimic pentru numele pe care nu le recunosc. Dreptunghiul stabilește caseta în care se scalează grafica, iar culoarea este o sugestie pe care vizualizatorul o poate respecta sau nu. Dacă o ștampilă trebuie să arate identic peste tot, calea de încredere nu este deloc o ștampilă standard: desenați semnul chiar dumneavoastră cu TextOut și cu apelurile de desenare sau plasați-l ca adnotare de text liber, al cărei aspect îl controlați. Apelați la ștampila standard atunci când vreți aspectul familiar al vizualizatorului și puteți tolera variația

Atașamentele de fișiere urmează aceeași formă de dreptunghi plus încărcătură. AddFileAttachmentAnnotation primește descrierea, calea fișierului de încorporat, un dreptunghi pentru pictograma de agrafă și o culoare. Fișierul călătorește în interiorul PDF-ului, iar pictograma este mânerul de care se folosește un cititor ca să îl extragă

Prin ce diferă adnotările de câmpurile AcroForm

Confuzia care costă cel mai mult timp este tratarea unei adnotări ca și cum ar fi un câmp de formular. Amândouă se atașează la pagină prin /Annots, iar un câmp de formular este de fapt un subtip special de adnotare (un widget), motiv pentru care par înrudite. Nu sunt interschimbabile. Un câmp de formular ține o valoare, are un nume, participă la ordinea de tabulare și poate fi trimis, resetat sau scriptat; pe acelea le creați cu apelurile AddTextField, AddCheckBox și AddPushButton, nu cu apelurile de adnotare de pe această pagină. O adnotare de marcaj ține un comentariu sau o formă, nu are nicio valoare de trimis și este instrumentul greșit din clipa în care trebuie să colectați date de intrare

Testul practic este simplu. Dacă un utilizator trebuie să scrie, să aleagă sau să dea clic, iar documentul să rețină asta, aveți nevoie de un câmp AcroForm. Dacă lăsați o notă, marcați o regiune sau ștampilați o stare care călătorește cu fișierul, dar nu este dată, aveți nevoie de o adnotare. Confundarea lor produce documente care arată bine și se comportă greșit: un „câmp” pe care nu îl poate completa nimeni sau un comentariu care dispare când un formular este resetat. Partea interactivă, cu tipuri de câmpuri, validare și acțiuni de trimitere, este un subiect propriu, tratat în parcurgerea câmpurilor și acțiunilor AcroForm

Alcătuirea unei pagini

Piesele se compun așa cum o face tot restul HotPDF. Setați proprietățile documentului, apelați BeginDoc, desenați conținutul de pagină de care aveți nevoie cu apelurile de text și grafică, adăugați adnotările deasupra și încheiați cu EndDoc. Adnotările se atașează la CurrentPage, deci după un AddPage ele aterizează pe pagina nouă, iar o notă gândită pentru pagina întâi va apărea discret pe pagina a doua dacă o adăugați după schimbarea de pagină

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;

Un ultim reflex pe care merită să vi-l formați atunci când ieșirea arată greșit: deschideți fișierul în mai mult de un vizualizator înainte să hotărâți că este codul de vină. Ștampilele și pictogramele de notă mai rare sunt vinovații obișnuiți, iar fiindcă adnotarea este o cerere către cititor, nu niște pixeli pictați, o diferență între Acrobat și un vizualizator ușor este adesea specificația funcționând așa cum a fost gândită, nu un defect în apelul dumneavoastră

Apelurile de adnotare prezentate aici fac parte din HotPDF Delphi Component pentru Delphi și C++Builder