Техническа статия

PDF анотации в Delphi с HotPDF: Видове и правоъгълници

Една анотация не е съдържание на страницата. Когато извикате TextOut или начертаете правоъгълник, маркировките стават част от потока от съдържание на страницата, изпечени в байтовете, които рендерерът рисува. Анотацията е отделен речник, който виси на страницата чрез нейния масив /Annots, със собствен правоъгълник, собствен външен вид и собствен жизнен цикъл. Читателят може да я отвори, премести, скрие или премахне, без да докосва нито един глиф от основната страница. Това разделение е цялата причина, поради която анотациите съществуват, и също така е източникът на двете неща, които изненадват хората първо: къде попада дадена анотация и как изглежда, след като конкретен четец се сдобие с нея

HotPDF излага подтиповете анотации на ISO 32000 чрез семейство от извиквания AddXxxAnnotation на обекта на страницата. Всички те споделят една и съща форма: правоъгълник, който фиксира анотацията на страницата в потребителското пространство на PDF, някакъв полезен товар (текст, име на печат, двойка точки) и цвят. Уцелете правоъгълника правилно и по-голямата част от работата е свършена. Останалото е да знаете кои подтипове носят свой собствен външен вид и кои разчитат на четеца да ги нарисува

PDF страница, произведена от HotPDF, показваща икони на текстови бележки, текстови полета за свободен текст, квадратни и линейни маркировки, и печати за одобрение, разположени из цялата страница
Една страница, носеща няколко подтипа анотации едновременно: текстови бележки, свободен текст, геометрични маркировки и печати

Правоъгълникът е анотацията, а не текстът

Всяко извикване на анотация приема TRect и този правоъгълник означава нещо различно от координатите, които подавате на TextOut. За текстова бележка това е кликващата гореща точка, малкият регион, където стои иконата на бележката и където едно щракване отваря коментара. За квадрат или текстово поле със свободен текст това е видимият обхват на маркировката. За печат това е кутията, в която се мащабира изкуството на печата. Числата са точки от потребителското пространство на PDF, измерени от долния ляв ъгъл на страницата, като Y се увеличава нагоре, същата конвенция, която използва останалата част от HotPDF

Текстовата бележка е най-лекият подтип. Давате ѝ основния текст, правоъгълник за иконата, флаг за това дали се отваря по подразбиране, име на икона и цвят

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);

Правоъгълникът тук е умишлено малък, около двадесет пункта от страна, защото текстовата бележка е само икона, докато някой не щракне върху нея. Направете правоъгълника голям и няма да получите голяма бележка; ще получите огромна цел за щракване с икона, прикрепена към единия ъгъл. Флагът Open контролира дали изскачащият прозорец се показва, когато документът се зарежда. Задайте на шепа бележки True и те ще се подредят една върху друга и върху съдържанието, така че запазете това за единствената бележка, която наистина искате читателят да види веднага

Името на иконата идва от THPDFTextAnnotationType, което се картографира към стандартните икони за бележки: taComment, taKey, taNote, taHelp, taParagraph, taNewParagraph и taInsert. Иконата е единственото нещо, което типът променя. Той не променя поведението и си струва да знаете, че не всеки четец рисува всичките седем; безопасните при стари и нови четци са taComment, taNote и taHelp

Свободният текст пише върху страницата, но остава анотация

Анотацията за свободен текст изглежда като съдържание, тъй като текстът е видим без щракване, седейки в своя правоъгълник като надпис. Тя все още е анотация, с цялата разделимост, която това предполага, което е точно това, което искате за печат за преглед или етикет за чернова, който някой трябва да може да премахне по-късно. Сигнатурата разменя иконата и флага за отваряне със стойност за подравняване

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

Тук правоъгълникът има по-голямо значение, отколкото за текстова бележка, тъй като текстът се пренася и подравнява вътре в него. Оразмерете кутията твърде къса и текстът се изрязва по долния ръб; твърде тясна и се пренася на места, които не сте предвидили. Подравняването идва от THPDFFreeTextAnnotationJust и има само трите стойности. Тъй като свободният текст е маркираща анотация (markup annotation), читател, който отвори файла в редактор, може да го избере, премести или изтрие като единица, което е разликата, която решава дали посягате към свободен текст или просто начертавате думите с TextOut. Ако етикетът трябва да е постоянен, начертайте го. Ако е редакционен и е предвиден да отпадне, направете го анотация

Геометрични и линейни маркировки за посочване на неща

Квадратите, кръговете и линиите са маркировката, която използвате, за да посочите даден регион, вместо да го описвате с думи. AddCircleSquareAnnotation покрива двете форми на кутии чрез THPDFCSAnnotationType от csCircle или csSquare, като правоъгълникът задава границите на формата

// 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;

Обърнете внимание, че линейната анотация нарушава модела на правоъгълника: тя приема два записа THPDFCurrPoint, начало и край, защото линията се дефинира от нейните крайни точки, а не от ограничаваща кутия (bounding box). Цветът задава щриха. Ако искате върхове на стрелки, HotPDF има претоварвания на AddLineAnnotation, които приемат стилове на завършване на линии, но обикновената форма с три аргумента чертае гола линия, което обикновено е това, което иска изнесеният текст

Подтиповете за маркиране на текст работят върху регион, който вече сте оформили. AddHighlightAnnotation приема правоъгълник, незадължително съдържание и цвят, който по подразбиране е жълт, и оцветява областта по начина, по който би го направил маркер. Предвиден е да седи над реален текст, така че правоъгълникът трябва да съответства на границите на думите, които сте начертали, което означава, че обикновено го изчислявате от същите координати, които сте подали на TextOut, а не гадаете

Печатите зависят от четеца, за да ги рендира

Анотацията с печат е най-вероятно да изглежда различно при различните четци и причината си струва да се разбере. AddStampAnnotation назовава стандартен печат чрез THPDFStampAnnotationType, със стойности като satApproved, satConfidential, satFinal, satDraft и satForComment

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

Името на печата е заявка. PDF дефинира набора от стандартни имена на печати, но не и художественото оформление зад тях, така че всеки четец доставя свое собствено рендиране на „APPROVED“ или „CONFIDENTIAL“, а някои не рендират нищо за имена, които не разпознават. Правоъгълникът контролира кутията, в която се мащабира изкуството, а цветът е подсказка, която четецът може да уважи или да не уважи. Ако даден печат трябва да изглежда идентично навсякъде, надеждният път изобщо не е стандартен печат: начертайте марката сами с TextOut и извикванията за чертане, или го поставете като анотация за свободен текст, чийто външен вид контролирате. Посегнете към стандартния печат, когато искате познатия вид на четеца и можете да толерирате вариации

Прикачените файлове следват същата форма правоъгълник-плюс-полезен-товар. AddFileAttachmentAnnotation приема описанието, пътя на файла за вграждане, правоъгълник за иконата на кламер и цвят. Файлът се вози вътре в PDF-а, а иконата е дръжката, която четецът използва, за да го извлече

Как анотациите се различават от полетата на AcroForm

Объркването, което струва най-много време, е третирането на анотация като поле на формуляр. И двете се прикрепят към страницата чрез /Annots и полето на формуляр всъщност е специален подтип анотация (уиджет), поради което изглеждат свързани. Те не са взаимозаменяеми. Полето на формуляр съдържа стойност, има име, участва в реда на табулация и може да бъде изпратено, нулирано или скриптувано; създавате ги с извикванията AddTextField, AddCheckBox и AddPushButton, а не с извикванията на анотации на тази страница. Маркиращата анотация съдържа коментар или форма, няма стойност за изпращане и е грешният инструмент в момента, в който трябва да събирате входни данни

Практическият тест е прост. Ако даден потребител е предвиден да въвежда, избира или щраква и документът да го запомни, вие искате поле на AcroForm. Ако оставяте бележка, маркирате регион или поставяте печат за състояние, който пътува с файла, но не е данни, искате анотация. Смесването им произвежда документи, които изглеждат правилно и се държат грешно: „поле“, което никой не може да попълни, или коментар, който изчезва, когато формулярът се нулира. Интерактивната страна, с типове полета, валидиране и действия за изпращане, е своя собствена тема, разгледана в ръководството за полета и действия на AcroForm

Сглобяване на страница

Парчетата се композират по начина, по който го прави останалата част от HotPDF. Задайте свойства на документа, извикайте BeginDoc, начертайте каквото съдържание на страницата ви е необходимо с извикванията за текст и графика, добавете анотации отгоре и затворете с EndDoc. Анотациите се прикрепят към CurrentPage, така че след AddPage те попадат на новата страница, и бележка, която сте предвидили за първа страница, тихо ще се появи на втора страница, ако я добавите след прекъсването

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;

Още един последен рефлекс, който си струва да изградите, когато изходът изглежда грешно: отворете файла в повече от един четец, преди да решите, че кодът е счупен. Печатите и по-редките икони за бележки са обичайните виновници, и тъй като анотацията е заявка към четеца, а не изрисувани пиксели, разликата между Acrobat и олекотен четец често е спецификацията, работеща по предназначение, а не бъг във вашето извикване

Извикванията на анотации, показани тук, са част от HotPDF Component за Delphi и C++Builder