En annotering er ikke sideinnhold. Når du kaller TextOut eller tegner et rektangel, blir merkene en del av sidens innholdsstrøm (content stream), bakt inn i bytene som en gjengiver (renderer) maler. En annotering er en separat ordbok (dictionary) som henger på siden gjennom dens /Annots-array, med sitt eget rektangel, sitt eget utseende, og sin egen livssyklus. En leser kan åpne den, flytte den, skjule den, eller fjerne den uten å berøre en eneste glyff av den underliggende siden. Den separasjonen er hele grunnen til at annoteringer eksisterer, og det er også kilden til de to tingene som overrasker folk først: hvor en annotering lander, og hvordan den ser ut når en bestemt visningsapplikasjon (viewer) får tak i den
HotPDF eksponerer ISO 32000-annoteringsundertypene gjennom en familie av AddXxxAnnotation-kall på sideobjektet. De deler alle samme form: et rektangel som fester annoteringen på siden i PDF-brukerrom (user space), en nyttelast (tekst, et stempel-navn, et par punkter), og en farge. Få rektangelet riktig, og mesteparten av jobben er gjort. Resten er å vite hvilke undertyper (subtypes) som bærer sitt eget utseende (appearance), og hvilke som lener seg på visningsprogrammet for å tegne dem

Rektangelet er annoteringen, ikke teksten
Hvert annoteringskall tar en TRect, og det rektangelet betyr noe annet enn koordinatene du sender til TextOut. For et tekstnotat er det den klikkbare hotspot-en, den lille regionen der notatikonet sitter og der et klikk åpner kommentaren. For en firkant eller fri tekst-boks er det den synlige utstrekningen av markeringen (markup). For et stempel er det boksen stempelkunsten skaleres inn i. Tallene er PDF-brukerrom-punkter, målt fra nedre venstre hjørne av siden med Y økende oppover, den samme konvensjonen resten av HotPDF bruker
Et tekstnotat er den letteste undertypen. Du gir den selve brødteksten, et rektangel for ikonet, et flagg for om det åpnes som standard, et ikonnavn, og en farge
Pdf.CurrentPage.AddTextAnnotation(
'Anmelder: bekreft totalsummene på denne linjen før du signerer.',
Rect(120, 700, 140, 720), // ikon-hotspot, ~20pt kvadrat
False, // lukket til leseren klikker på den
taComment, // bobleikon
clBlue);
Rektangelet her er bevisst lite, rundt tjue punkter på en side, fordi et tekstnotat bare er et ikon frem til noen klikker på det. Gjør du rektangelet stort, får du ikke et stort notat; du får et overdimensjonert klikk-mål med ikonet festet til det ene hjørnet. Open-flagget kontrollerer om popup-vinduet vises når dokumentet lastes. Setter du en håndfull notater til True stables de oppå hverandre og oppå innholdet, så reserver det for det ene notatet du faktisk vil at leseren skal se umiddelbart
Ikonnavnet kommer fra THPDFTextAnnotationType, som kartlegger (maps) til standard notatikonene: taComment, taKey, taNote, taHelp, taParagraph, taNewParagraph, og taInsert. Ikonet er det eneste typen endrer. Det endrer ikke oppførselen, og det er verdt å vite at ikke alle visningsprogrammer tegner alle sju; de sikre på tvers av gamle og nye lesere er taComment, taNote, og taHelp
Fri tekst skriver på siden, men forblir en annotering
En fri tekst-annotering ser ut som innhold fordi teksten er synlig uten et klikk, sittende i sitt rektangel som en bildetekst (caption). Det er fortsatt en annotering, med all separerbarheten det innebærer, som er akkurat det du vil ha for et vurderingsstempel (review stamp) eller en utkast-etikett (draft label) som noen skal kunne fjerne senere. Signaturen bytter ikonet og åpen-flagget for en justeringsverdi (justification value)
Pdf.CurrentPage.AddFreeTextAnnotation(
'UTKAST - ikke for distribusjon',
Rect(200, 210, 400, 235), // boksen teksten legges i
ftCenter, // ftLeftJust / ftCenter / ftRightJust
clRed);
Her betyr rektangelet mer enn det gjør for et tekstnotat, fordi teksten brytes (wraps) og justeres inni det. Dimensjonerer du boksen for kort, klippes teksten ved den nederste kanten; for smal og den brytes på steder du ikke hadde tenkt. Justeringen kommer fra THPDFFreeTextAnnotationJust og har bare de tre verdiene. Siden fri tekst er en markerings-annotering (markup annotation), kan en leser som åpner filen i et redigeringsprogram (editor) velge den, flytte den, eller slette den som en enhet, noe som er forskjellen som avgjør om du griper til fri tekst eller bare tegner ordene med TextOut. Hvis etiketten må være permanent, tegn den. Hvis den er redaksjonell og ment å fjernes, gjør den til en annotering
Geometriske markeringer og linjemarkeringer for å peke på ting
Firkanter, sirkler, og linjer er markeringen (markup) du bruker for å peke på en region i stedet for å beskrive den med ord. AddCircleSquareAnnotation dekker de to boksformene gjennom en THPDFCSAnnotationType på csCircle eller csSquare, med rektangelet som gir grensene (bounds) for formen
// En boks tegnet rundt en figur som trenger oppmerksomhet
Pdf.CurrentPage.AddCircleSquareAnnotation(
'Sjekk denne regionen mot kildedataene',
Rect(50, 300, 120, 360),
csSquare,
clGreen);
// En linje, gitt to punkter snarere enn et rektangel
var
StartPt, EndPt: THPDFCurrPoint;
begin
StartPt.X := 130; StartPt.Y := 360;
EndPt.X := 250; EndPt.Y := 320;
Pdf.CurrentPage.AddLineAnnotation(
'Peker fra notatet til figuren',
StartPt, EndPt,
clBlue);
end;
Legg merke til at linje-annoteringen bryter med rektangel-mønsteret: den tar to THPDFCurrPoint-poster (records), en start og en slutt, fordi en linje er definert av dens endepunkter, ikke av en avgrensningsboks (bounding box). Fargen setter strøket (stroke). Hvis du vil ha pilspisser, har HotPDF overbelastninger (overloads) av AddLineAnnotation som aksepterer linje-avslutning-stiler (line-ending styles), men den enkle tre-argumenters-formen tegner en bar linje, noe som vanligvis er hva en "callout" vil ha
Tekst-markering-undertyper fungerer på en region du allerede har lagt ut (laid out). AddHighlightAnnotation tar et rektangel, valgfritt innhold, og en farge som som standard er gul, og toner området på den måten en merkepenn ville gjort. Den er ment å sitte over ekte tekst, så rektangelet bør samsvare med grensene til ordene du tegnet, noe som betyr at du generelt beregner den fra de samme koordinatene du sendte til TextOut fremfor å gjette
Stempler avhenger av at visningsprogrammet gjengir dem
En stempel-annotering er den som har størst sannsynlighet for å se annerledes ut fra én leser til den neste, og det er verdt å forstå grunnen til det. AddStampAnnotation navngir et standardstempel gjennom THPDFStampAnnotationType, med verdier som satApproved, satConfidential, satFinal, satDraft, og satForComment
Pdf.CurrentPage.AddStampAnnotation(
'Godkjent for utgivelse ved gjennomgang',
Rect(50, 400, 200, 440),
satApproved,
clGreen);
Stempelnavnet er en forespørsel. PDF definerer settet av standard stempelnavn, men ikke kunsten bak dem, så hver visningsapplikasjon (viewer) leveres med sin egen gjengivelse (rendering) av "APPROVED" (Godkjent) eller "CONFIDENTIAL" (Konfidensielt), og noen få gjengir ingenting i det hele tatt for navn de ikke kjenner igjen. Rektangelet kontrollerer boksen kunsten skaleres inn i, og fargen er et hint viseren kan, eller kanskje ikke, respektere. Hvis et stempel må se identisk ut overalt, er den pålitelige ruten (dependable route) ikke et standardstempel i det hele tatt: tegn merket selv med TextOut og tegnekallene, eller plasser det som en fri tekst-annotering hvor du kontrollerer utseendet. Grip etter standardstempelet når du ønsker viserens velkjente utseende og kan tolerere variasjonen
Filvedlegg følger den samme rektangel-pluss-nyttelast-formen. AddFileAttachmentAnnotation tar beskrivelsen, stien til filen som skal bygges inn (embed), et rektangel for bindersikonet, og en farge. Filen rir inne i PDF-en, og ikonet er håndtaket en leser bruker for å trekke den ut
Hvordan annoteringer skiller seg fra AcroForm-felt
Forvirringen som koster mest tid er å behandle en annotering som om den var et skjemafelt (form field). Begge festes til siden gjennom /Annots, og et skjemafelt er faktisk en spesiell annoteringsundertype (en widget), som er grunnen til at de ser beslektede ut. De kan imidlertid ikke byttes om på (are not interchangeable). Et skjemafelt har en verdi, har et navn, deltar i fanerekkefølge (tab order), og kan sendes inn (submitted), tilbakestilles (reset), eller scriptes; du oppretter disse med AddTextField, AddCheckBox, og AddPushButton-kall, ikke annoteringskallene på denne siden. En markering-annotering inneholder en kommentar eller en form, har ingen verdi å sende inn, og er feil verktøy det øyeblikket du trenger å samle inndata
Den praktiske testen er enkel. Hvis en bruker er ment å skrive, velge, eller klikke og la dokumentet huske det, vil du ha et AcroForm-felt. Hvis du legger igjen et notat, markerer et område, eller stempler en status som reiser med filen, men som ikke er data, vil du ha en annotering. Å blande dem sammen produserer dokumenter som ser riktige ut og oppfører seg feil: et "felt" ingen kan fylle ut, eller en kommentar som forsvinner når et skjema tilbakestilles (reset). Den interaktive siden, med felttyper, validering, og send-handlinger (submit actions), er et eget emne som dekkes i AcroForm-felt og -handlinger gjennomgangen
Sette sammen en side
Brikkene settes sammen på samme måte som resten av HotPDF gjør. Angi dokumentegenskaper, kall BeginDoc, tegn det sideinnholdet du trenger med tekst- og grafikkkallene, legg til annoteringer på toppen, og lukk med EndDoc. Annoteringer festes til CurrentPage, så etter en AddPage lander de på den nye siden, og et notat du mente for side én vil stille og rolig dukke opp på side to hvis du legger det til etter bruddet (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, 'Kvartalstall, utkast for gjennomgang');
Pdf.CurrentPage.AddTextAnnotation(
'Bekreft totalsummene før du signerer.',
Rect(50, 720, 70, 740), False, taComment, clBlue);
Pdf.CurrentPage.AddFreeTextAnnotation(
'UTKAST', Rect(450, 720, 540, 745), ftCenter, clRed);
Pdf.CurrentPage.AddStampAnnotation(
'For kommentar', Rect(50, 660, 180, 695), satForComment, clGreen);
Pdf.EndDoc;
finally
Pdf.Free;
end;
En siste refleks (reflex) verdt å bygge når utdata (output) ser feil ut: åpne filen i mer enn ett visningsprogram før du bestemmer deg for at koden er ødelagt. Stempler og de sjeldnere notatikonene er de vanlige synderne, og fordi annoteringen er en forespørsel til leseren fremfor malte piksler, er en forskjell mellom Acrobat og en lettvekts-viser (lightweight viewer) ofte spesifikasjonen som fungerer som designet, ikke en feil (bug) i kallet ditt
Annoteringskallene vist her er en del av HotPDF-komponenten for Delphi og C++Builder